This study allows us to revisit/renew
- Regression modeling
- Properties of Least Squares/Fitting “a line”
- Multiple observation
Datasets for this study are
- The main file: gauge.txt
- Supplementary large-scale files: download the following folder Full Resolution Data.zip More information about the supplementary file can be found at http://iabp.apl.washington.edu/data.html as well as http://nsidc.org/data/G00791
Question
The aim of this lab is to provide a simple procedure for converting gain into density when the gauge is in operation. Keep in mind that the experiment was conducted by varying density and measuring the response in gain, but when the gauge is ultimately in use, the snow-pack density is to be estimated from the measured gain.
Setup
df <- read.table('gauge-1wb1wa6-2gpel41.txt', header=TRUE)
df <- df[order(df$density), ] # Sort from least to greatest density
m <- 9 # Number of distinct block densities
t <- 10 # Number of replicate measurements
#install.packages('L1pack')
#install.packages("quantreg")
library(L1pack) # Used for least absolute deviations regression line
library(quantreg) # Used for quantile regression line
Loading required package: SparseM
Attaching package: ‘SparseM’
The following object is masked from ‘package:base’:
backsolve
Scenario 1: Fitting
Use the data to fit the gain, or a transformation of gain, to density. Try sketching the least squares line on a scatter plot.
- Do the residuals indicate any problems with the fit?
- If the densities of the polyethylene blocks are not reported exactly, how might this affect the fit?
- What if the blocks of polyethylene were not measured in random order (location)?
# Plot raw data
title <- 'Density vs. Gain'
x.axis <- expression('Density (g/cm'^3*')')
y.axis <- 'Gain'
x.range <- c(0, .7)
y.range <- c(2.5, 6)
plot(df, main=title, xlab=x.axis, ylab=y.axis, xlim=x.range)

# Take log transformation of response variable (gain)
y.log.axis = 'log(Gain)'
df.log = data.frame(df['density'], log(df['gain']))
plot(df.log, main=title, xlab=x.axis, ylab=y.log.axis, xlim=x.range, ylim=y.range)

# Average replicate measurements
df.log.avg = aggregate(list(gain=df.log$gain), by=list(density=df.log$density), FUN=mean)
plot(df.log.avg, main=title, xlab=x.axis, ylab=y.log.axis, xlim=x.range, ylim=y.range)

# Fit gain to density
least.squares <- lm(gain~density, data=df.log.avg)
lad <- lad(gain~density, data=df.log.avg)
quant <- rq(gain~density, tau=.5, data=df.log.avg)
plot(df.log, main=title, xlab=x.axis, ylab=y.log.axis, xlim=x.range, ylim=y.range)
abline(least.squares, col='red')
abline(lad, col='blue')
abline(quant, col='green')
legend('topright', legend=c('Least Squares Regression Line', 'Least Absolute Deviations Regression Line', '50% Quantile Regression Line'), col=c('red', 'blue', 'green'), lty=1)

c(cor(df.log.avg), summary(least.squares)$r.squared)
<<<<<<< HEAD
[1] 1.0000000 -0.9984469 -0.9984469 1.0000000 0.9968963
least.squares
=======
[1] 1.0000000 -0.9984469 -0.9984469 1.0000000 0.9968963
least.squares
>>>>>>> d4f5f9c0a005e74c03c52f2335922402dbf39c0f
Call:
lm(formula = gain ~ density, data = df.log.avg)
Coefficients:
(Intercept) density
5.997 -4.606
lad
Call:
lad(formula = gain ~ density, data = df.log.avg)
Converged in 4 iterations
Coefficients:
(Intercept) density
5.9850 -4.5935
Degrees of freedom: 9 total; 7 residual
Scale estimate: 0.06926379
quant
Call:
rq(formula = gain ~ density, tau = 0.5, data = df.log.avg)
Coefficients:
(Intercept) density
5.985029 -4.593460
Degrees of freedom: 9 total; 7 residual
# Check conditions for linear regression: linearity, normality of residuals, and constant variability
least.squares.residuals <- data.frame(df.log['density'], df.log['gain'] - rep(predict(least.squares), each=10))
lad.residuals <- data.frame(df.log['density'], df.log['gain'] - rep(predict(lad), each=10))
quant.residuals <- data.frame(df.log['density'], df.log['gain'] - rep(predict(quant), each=10))
title.residuals1 <- 'Residuals of Least Squares Regression Line'
title.residuals2 <- 'Residuals of Least Absolute Deviations Regression Line'
title.residuals3 <- 'Residuals of 50% Quantile Regression Line'
plot(least.squares.residuals$gain, main=title.residuals1, ylab=y.axis)
abline(0, 0, col='red')

plot(lad.residuals$gain, main=title.residuals2, ylab=y.axis)
abline(0, 0, col='blue')

plot(quant.residuals$gain, main=title.residuals3, ylab=y.axis)
abline(0, 0, col='green')

num.bins <- 12
hist(least.squares.residuals$gain, breaks=num.bins, main=title.residuals1, xlab=y.axis, col='red')

hist(lad.residuals$gain, breaks=num.bins, main=title.residuals2, xlab=y.axis, col='blue')

hist(quant.residuals$gain, breaks=num.bins, main=title.residuals3, xlab=y.axis, col='green')

qqnorm(least.squares.residuals$gain, main=paste('Normal Q-Q Plot with', title.residuals1), cex.main=1)
qqline(least.squares.residuals$gain, col='red')

qqnorm(lad.residuals$gain, main=paste('Normal Q-Q Plot with', title.residuals2), cex.main=1)
qqline(lad.residuals$gain, col='blue')

qqnorm(quant.residuals$gain, main=paste('Normal Q-Q Plot with', title.residuals3), cex.main=1)
qqline(quant.residuals$gain, col='green')

Scenario 2: Predicting
Ultimately we are interested in answering questions such as: Given a gain reading of 38.6, what is the density of the snow-pack? Given a gain reading of 426.7, what is the density of the snow-pack? These two numeric values, 38.6 and 426.7, were chosen because they are the average gains for the 0.508 and 0.001 densities, respectively.
- Develop a procedure for adding bands around your least squares line that can be used to make interval estimates for the snow-pack density from gain measurements. Keep in mind how the data were collected: several measurements of gain were taken for polyenythylene blocks of known density.
# Predictions
PredictLogGain <- function(density)
predict(least.squares, data.frame(density=density)) # Predict log(gain) using density
PredictDensityLeastSquares <- function(gain) {
intercept <- coef(least.squares)[[1]]
slope <- coef(least.squares)[[2]]
(log(gain) - intercept) / slope # Predict density using gain
}
PredictDensityLad <- function(gain) {
intercept <- coef(lad)[[1]]
slope <- coef(lad)[[2]]
(log(gain) - intercept) / slope # Predict density using gain
}
PredictDensityQuant <- function(gain) {
intercept <- coef(quant)[[1]]
slope <- coef(quant)[[2]]
(log(gain) - intercept) / slope # Predict density using gain
}
# 95% prediction and confidence intervals of log(gain) using density
t <- qt(.975, df=m-2)
mean.density <- mean(df.log.avg$density)
summation <- sum((df.log.avg$density - mean.density) ^ 2)
s2 <- aggregate(list(variance=least.squares.residuals$gain), by=list(density=least.squares.residuals$density), FUN=var)
s.pooled <- sqrt(mean(s2$variance))
center.expr <- quote(center <- PredictLogGain(density))
ci.width.expr <- quote(width <- t * s.pooled * sqrt(1/m + (density-mean.density)^2 / summation))
pi.width.expr <- quote(width <- t * s.pooled * sqrt(1 + 1/m + (density-mean.density)^2 / summation))
LogGainCiLower <- function(density) {
eval(center.expr)
eval(ci.width.expr)
center - width
}
LogGainCiUpper <- function(density) {
eval(center.expr)
eval(ci.width.expr)
center + width
}
LogGainPiLower <- function(density) {
eval(center.expr)
eval(pi.width.expr)
center - width
}
LogGainPiUpper <- function(density) {
eval(center.expr)
eval(pi.width.expr)
center + width
}
# Add bands around least squares line
plot(df.log, main=title, xlab=x.axis, ylab=y.log.axis, xlim=x.range, ylim=y.range)
abline(least.squares, col='red')
ci.col <- 'purple'
pi.col <- 'blue'
symbol <- '-'
size <- 1.5
line.type <- 3
line.width <- 0.7
confidence.intervals <- data.frame(density=df.log.avg$density, lower=LogGainCiLower(df.log.avg$density), upper=LogGainCiUpper(df.log.avg$density))
points(x=confidence.intervals$density, y=confidence.intervals$lower, col=ci.col, pch=symbol, cex=size)
points(x=confidence.intervals$density, y=confidence.intervals$upper, col=ci.col, pch=symbol, cex=size)
lines(x=confidence.intervals$density, y=confidence.intervals$lower, col=ci.col, lty=line.type, lwd=line.width)
lines(x=confidence.intervals$density, y=confidence.intervals$upper, col=ci.col, lty=line.type, lwd=line.width)
prediction.intervals <- data.frame(density=df.log.avg$density, lower=LogGainPiLower(df.log.avg$density), upper=LogGainPiUpper(df.log.avg$density))
points(x=prediction.intervals$density, y=prediction.intervals$lower, col=pi.col, pch=symbol, cex=size)
points(x=prediction.intervals$density, y=prediction.intervals$upper, col=pi.col, pch=symbol, cex=size)
lines(x=prediction.intervals$density, y=prediction.intervals$lower, col=pi.col, lty=line.type, lwd=line.width)
lines(x=prediction.intervals$density, y=prediction.intervals$upper, col=pi.col, lty=line.type, lwd=line.width)
legend('topright', legend=c('Least Squares Regression Line', '95% Confidence Interval Bands', '95% Prediction Interval Bands'), col=c('red', ci.col, pi.col), lty=1)

# 95% prediction and confidence intervals of density using gain
end.points <- c(-1, 3) # Interval to search the root in
DensityCi <- function(gain) {
lower <- uniroot(function(density) log(gain) - LogGainCiLower(density), interval=end.points)[[1]]
upper <- uniroot(function(density) log(gain) - LogGainCiUpper(density), interval=end.points)[[1]]
c(lower, upper)
}
DensityPi <- function(gain) {
lower <- uniroot(function(density) log(gain) - LogGainPiLower(density), end.points)[[1]]
upper <- uniroot(function(density) log(gain) - LogGainPiUpper(density), end.points)[[1]]
c(lower, upper)
}
# Point and interval estimates for example gain readings
PredictDensityLeastSquares(38.6) # 38.6 is the average gain for 0.508 density
[1] 0.5089113
PredictDensityLad(38.6)
[1] 0.5076298
PredictDensityQuant(38.6)
[1] 0.5076298
DensityCi(38.6)
[1] 0.5011879 0.5169000
DensityPi(38.6)
[1] 0.4889568 0.5291323
PredictDensityLeastSquares(426.7) # 426.7 is the average gain for 0.001 density
[1] -0.01276954
PredictDensityLad(426.7)
[1] -0.01546807
PredictDensityQuant(426.7)
[1] -0.01546811
DensityCi(426.7)
[1] -0.024285866 -0.001769193
DensityPi(426.7)
[1] -0.034644666 0.008618629
Scenario 3: Cross-Validation
To check how well your procedure works, omit the set of measurements corresponding to the block of density 0.508, apply your “estimation”/calibration procedure to the remaining data, and provide an interval estimate for the density of a block with an average reading of 38.6. Where does the actual density fall in the interval? Try the same test, for the set of measurements at the 0.001 density.
for (omitted in c(0.508, 0.001)) {
# Omit measurements corresponding to the specified density
df.log.omitted = df.log[which(df.log['density'] != omitted), ]
df.log.avg.omitted <- df.log.avg[which(df.log.avg['density'] != omitted), ]
# Redo calculations using modified dataset
least.squares <- lm(gain~density, data=df.log.avg.omitted)
mean.density <- mean(df.log.avg.omitted$density)
summation <- sum((df.log.avg.omitted$density - mean.density) ^ 2)
s2 <- aggregate(list(variance=least.squares.residuals$gain), by=list(density=least.squares.residuals$density), FUN=var)
s.pooled <- sqrt(mean(s2$variance))
ci.width.expr <- quote(width <- t * s.pooled * sqrt(1/(m-1) + (density-mean.density)^2 / summation))
pi.width.expr <- quote(width <- t * s.pooled * sqrt(1 + 1/(m-1) + (density-mean.density)^2 / summation))
plot(df.log.omitted, main=title, xlab=x.axis, ylab=y.log.axis, xlim=x.range, ylim=y.range)
abline(least.squares, col='red')
ci.col <- 'purple'
pi.col <- 'blue'
symbol <- '-'
size <- 1.5
line.type <- 3
line.width <- 0.7
confidence.intervals <- data.frame(density=df.log.avg.omitted$density, lower=LogGainCiLower(df.log.avg.omitted$density), upper=LogGainCiUpper(df.log.avg.omitted$density))
points(x=confidence.intervals$density, y=confidence.intervals$lower, col=ci.col, pch=symbol, cex=size)
points(x=confidence.intervals$density, y=confidence.intervals$upper, col=ci.col, pch=symbol, cex=size)
lines(x=confidence.intervals$density, y=confidence.intervals$lower, col=ci.col, lty=line.type, lwd=line.width)
lines(x=confidence.intervals$density, y=confidence.intervals$upper, col=ci.col, lty=line.type, lwd=line.width)
prediction.intervals <- data.frame(density=df.log.avg.omitted$density, lower=LogGainPiLower(df.log.avg.omitted$density), upper=LogGainPiUpper(df.log.avg.omitted$density))
points(x=prediction.intervals$density, y=prediction.intervals$lower, col=pi.col, pch=symbol, cex=size)
points(x=prediction.intervals$density, y=prediction.intervals$upper, col=pi.col, pch=symbol, cex=size)
lines(x=prediction.intervals$density, y=prediction.intervals$lower, col=pi.col, lty=line.type, lwd=line.width)
lines(x=prediction.intervals$density, y=prediction.intervals$upper, col=pi.col, lty=line.type, lwd=line.width)
legend('topright', legend=c('Least Squares Regression Line', '95% Confidence Interval Bands', '95% Prediction Interval Bands'), col=c('red', ci.col, pi.col), lty=1)
print(PredictDensityLeastSquares(38.6)) # 38.6 is the average gain for 0.508 density
print(DensityCi(38.6))
print(DensityPi(38.6))
print(PredictDensityLeastSquares(426.7)) # 426.7 is the average gain for 0.001 density
print(DensityCi(426.7))
print(DensityPi(426.7))
}
[1] 0.5091927
[1] 0.5006695 0.5180406
[1] 0.4889184 0.5297925
[1] -0.0128045
[1] -0.024342164 -0.001790802
[1] -0.034760736 0.008598777

[1] 0.5092919
[1] 0.5014370 0.5174323
[1] 0.4890257 0.5298473
[1] -0.02051733
[1] -0.035344991 -0.006521825
[1] -0.044604850 0.002738127

Additional Scenario: Temperature, DOY, and Latitude.
Use the additional dataset to construct a model fitting temperature with DOY, latitude, and other reasonable features. Try sketching the least squares line on a scatter plot. We aim to investigate the relationship between temperature and the DOY, and its latitude.
# Check the correlation
data <- read.csv('Full Resolution Data/64506420.csv', header=TRUE)
data <- data[,c('Hour','DOY','POS_DOY','Lat','Lon','Ts','BP')]
# Drop the extreme outlier case
#data <- data[which(data$Ts>-200),]
data_matrix <- as.matrix(data)
# Correlation Matrix
corr_matrix <- cor(data_matrix)
corr_matrix
Hour DOY POS_DOY Lat Lon Ts BP
Hour 1.000000000 -0.006779489 -0.006775002 -0.007511024 0.01217860 0.008592576 0.02505819
DOY -0.006779489 1.000000000 0.999999958 0.903704617 -0.68012490 -0.906918658 -0.17232397
POS_DOY -0.006775002 0.999999958 1.000000000 0.903696909 -0.68013445 -0.906916964 -0.17230481
Lat -0.007511024 0.903704617 0.903696909 1.000000000 -0.59748962 -0.958835395 -0.29666821
Lon 0.012178596 -0.680124899 -0.680134450 -0.597489620 1.00000000 0.564136723 -0.02981279
Ts 0.008592576 -0.906918658 -0.906916964 -0.958835395 0.56413672 1.000000000 0.20223136
BP 0.025058188 -0.172323969 -0.172304805 -0.296668215 -0.02981279 0.202231363 1.00000000
# Group by DOY and average replicated measurements
data$DOY <- round(data$DOY,0)
data.avg = aggregate(list(data=data[,c('Ts','Lat')]), by=list(DOY=data$DOY), FUN=mean)
# least squares line
ggplot(data.avg,aes(x=data.avg$DOY, y=data.avg$data.Ts)) +
geom_point(color='#2980B9', size = 4) +
<<<<<<< HEAD
geom_smooth(method=lm, color='#2C3E50') +ggtitle(label ="Least Squares Regression Line") + xlab("Day Of Year") +
ylab("Temperature")

fit1<-lm(formula = data.Ts ~ DOY, data = data.avg)
summary(fit1)
Call:
lm(formula = data.Ts ~ DOY, data = data.avg)
Residuals:
Min 1Q Median 3Q Max
-0.95439 -0.34633 0.03139 0.35247 0.84693
=======
<<<<<<< HEAD
geom_smooth(method=lm, color='#2C3E50')

ggplot(data,aes(x=Lat, y=Ts)) +
geom_point(color='#2980B9', size = 4) +
geom_smooth(method=lm, color='#2C3E50')

title.residuals1 <- 'Residuals of Least Squares Regression Line'
plot(fit$residuals, main=title.residuals1)
abline(0, 0, col='red')

num.bins <- 10
hist(fit$residuals, breaks=num.bins, main=title.residuals1, xlab='Temperature', col='red')

qqnorm(fit$residuals, main=paste('Normal Q-Q Plot with', title.residuals1), cex.main=1)
qqline(fit$residuals, col='red')

=======
geom_smooth(method=lm, color='#2C3E50')
>>>>>>> d4f5f9c0a005e74c03c52f2335922402dbf39c0f
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 9.353218 0.114242 81.87 <2e-16 ***
DOY -0.040253 0.001989 -20.23 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.4741 on 86 degrees of freedom
Multiple R-squared: 0.8264, Adjusted R-squared: 0.8244
F-statistic: 409.4 on 1 and 86 DF, p-value: < 2.2e-16
ggplot(data.avg,aes(x=data.avg$data.Lat, y=data.avg$data.Ts)) +
geom_point(color='#2980B9', size = 4) +
geom_smooth(method=lm, color='#2C3E50') +ggtitle(label ="Least Squares Regression Line")+ xlab("Lattitude") +
ylab("Temperature")

fit2<-lm(formula = data.Ts ~ data.Lat, data = data.avg)
summary(fit2)
Call:
lm(formula = data.Ts ~ data.Lat, data = data.avg)
Residuals:
Min 1Q Median 3Q Max
-0.51377 -0.26924 -0.04201 0.24403 0.64902
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 47.9901 1.2672 37.87 <2e-16 ***
data.Lat -0.6202 0.0193 -32.14 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.3155 on 86 degrees of freedom
Multiple R-squared: 0.9231, Adjusted R-squared: 0.9222
F-statistic: 1033 on 1 and 86 DF, p-value: < 2.2e-16
# Polynomial Regression Line
fit3<-lm(formula = data.Ts ~ DOY + data.Lat, data = data.avg)
summary(fit3)
<<<<<<< HEAD
Call:
lm(formula = data.Ts ~ DOY + data.Lat, data = data.avg)
Residuals:
Min 1Q Median 3Q Max
-0.60721 -0.22496 -0.00537 0.25822 0.61356
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 40.049638 2.673979 14.978 < 2e-16 ***
DOY -0.009756 0.002936 -3.322 0.00132 **
data.Lat -0.491566 0.042805 -11.484 < 2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.2985 on 85 degrees of freedom
Multiple R-squared: 0.932, Adjusted R-squared: 0.9304
F-statistic: 582.1 on 2 and 85 DF, p-value: < 2.2e-16
qqnorm(fit2$residuals, main=paste('Normal Q-Q Plot with', title.residuals1), cex.main=1)
qqline(fit2$residuals, col='red')
=======
>>>>>>> 8826eee1488bdd27557439752deda8eb4e450389
# Attempt for Multiple Regressions
data$Midnights <- 0
data$Midnights[which(data$Hour<6)] <- 1
data$Mornings <- 0
data$Mornings[which(data$Hour>=6 & data$Hour<11)] <- 1
data$Noon <- 0
data$Noon[which(data$Hour>=11 & data$Hour<15)] <- 1
data$Afternoon <- 0
data$Afternoon[which(data$Hour>=15 & data$Hour<20)] <- 1
data$Nights <- 0
data$Nights[which(data$Hour>=20)] <- 1
>>>>>>> d4f5f9c0a005e74c03c52f2335922402dbf39c0f

title.residuals1 <- 'Residuals of Least Square Regression Line'
plot(fit2$residuals, main=title.residuals1, ylab = "Standardized Residuals")
abline(0, 0, col='red')

<<<<<<< HEAD
LS0tCnRpdGxlOiAnQ0FTRSBTVFVEWSA0OicKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKVGhpcyBzdHVkeSBhbGxvd3MgdXMgdG8gcmV2aXNpdC9yZW5ldwoKMS4gUmVncmVzc2lvbiBtb2RlbGluZwoyLiBQcm9wZXJ0aWVzIG9mIExlYXN0IFNxdWFyZXMvRml0dGluZyAiYSBsaW5lIgozLiBNdWx0aXBsZSBvYnNlcnZhdGlvbgoKRGF0YXNldHMgZm9yIHRoaXMgc3R1ZHkgYXJlCgoxLiBUaGUgbWFpbiBmaWxlOiBnYXVnZS50eHQKMi4gU3VwcGxlbWVudGFyeSBsYXJnZS1zY2FsZSBmaWxlczogZG93bmxvYWQgdGhlIGZvbGxvd2luZyBmb2xkZXIgRnVsbCBSZXNvbHV0aW9uIERhdGEuemlwIE1vcmUgaW5mb3JtYXRpb24gYWJvdXQgdGhlIHN1cHBsZW1lbnRhcnkgZmlsZSBjYW4gYmUgZm91bmQgYXQgaHR0cDovL2lhYnAuYXBsLndhc2hpbmd0b24uZWR1L2RhdGEuaHRtbCBhcyB3ZWxsIGFzIGh0dHA6Ly9uc2lkYy5vcmcvZGF0YS9HMDA3OTEKCgojIyBRdWVzdGlvbgpUaGUgYWltIG9mIHRoaXMgbGFiIGlzIHRvIHByb3ZpZGUgYSBzaW1wbGUgcHJvY2VkdXJlIGZvciBjb252ZXJ0aW5nIGdhaW4gaW50byBkZW5zaXR5IHdoZW4gdGhlIGdhdWdlIGlzIGluIG9wZXJhdGlvbi4gS2VlcCBpbiBtaW5kIHRoYXQgdGhlIGV4cGVyaW1lbnQgd2FzIGNvbmR1Y3RlZCBieSB2YXJ5aW5nIGRlbnNpdHkgYW5kIG1lYXN1cmluZyB0aGUgcmVzcG9uc2UgaW4gZ2FpbiwgYnV0IHdoZW4gdGhlIGdhdWdlIGlzIHVsdGltYXRlbHkgaW4gdXNlLCB0aGUgc25vdy1wYWNrIGRlbnNpdHkgaXMgdG8gYmUgZXN0aW1hdGVkIGZyb20gdGhlIG1lYXN1cmVkIGdhaW4uCgoKIyMgU2V0dXAKYGBge3J9CmRmIDwtIHJlYWQudGFibGUoJ2dhdWdlLTF3YjF3YTYtMmdwZWw0MS50eHQnLCBoZWFkZXI9VFJVRSkKZGYgPC0gZGZbb3JkZXIoZGYkZGVuc2l0eSksIF0gICMgU29ydCBmcm9tIGxlYXN0IHRvIGdyZWF0ZXN0IGRlbnNpdHkKCm0gPC0gOSAgIyBOdW1iZXIgb2YgZGlzdGluY3QgYmxvY2sgZGVuc2l0aWVzCnQgPC0gMTAgICMgTnVtYmVyIG9mIHJlcGxpY2F0ZSBtZWFzdXJlbWVudHMKCiNpbnN0YWxsLnBhY2thZ2VzKCdMMXBhY2snKQojaW5zdGFsbC5wYWNrYWdlcygicXVhbnRyZWciKQpsaWJyYXJ5KEwxcGFjaykgICMgVXNlZCBmb3IgbGVhc3QgYWJzb2x1dGUgZGV2aWF0aW9ucyByZWdyZXNzaW9uIGxpbmUKbGlicmFyeShxdWFudHJlZykgICMgVXNlZCBmb3IgcXVhbnRpbGUgcmVncmVzc2lvbiBsaW5lCmBgYAoKCiMjIFNjZW5hcmlvIDE6IEZpdHRpbmcKVXNlIHRoZSBkYXRhIHRvIGZpdCB0aGUgZ2Fpbiwgb3IgYSB0cmFuc2Zvcm1hdGlvbiBvZiBnYWluLCB0byBkZW5zaXR5LiBUcnkgc2tldGNoaW5nIHRoZSBsZWFzdCBzcXVhcmVzIGxpbmUgb24gYSBzY2F0dGVyIHBsb3QuCgoqIERvIHRoZSByZXNpZHVhbHMgaW5kaWNhdGUgYW55IHByb2JsZW1zIHdpdGggdGhlIGZpdD8KKiBJZiB0aGUgZGVuc2l0aWVzIG9mIHRoZSBwb2x5ZXRoeWxlbmUgYmxvY2tzIGFyZSBub3QgcmVwb3J0ZWQgZXhhY3RseSwgaG93IG1pZ2h0IHRoaXMgYWZmZWN0IHRoZSBmaXQ/CiogV2hhdCBpZiB0aGUgYmxvY2tzIG9mIHBvbHlldGh5bGVuZSB3ZXJlIG5vdCBtZWFzdXJlZCBpbiByYW5kb20gb3JkZXIgKGxvY2F0aW9uKT8KYGBge3J9CiMgUGxvdCByYXcgZGF0YQp0aXRsZSA8LSAnRGVuc2l0eSB2cy4gR2FpbicKeC5heGlzIDwtIGV4cHJlc3Npb24oJ0RlbnNpdHkgKGcvY20nXjMqJyknKQp5LmF4aXMgPC0gJ0dhaW4nCngucmFuZ2UgPC0gYygwLCAuNykKeS5yYW5nZSA8LSBjKDIuNSwgNikKcGxvdChkZiwgbWFpbj10aXRsZSwgeGxhYj14LmF4aXMsIHlsYWI9eS5heGlzLCB4bGltPXgucmFuZ2UpCgoKIyBUYWtlIGxvZyB0cmFuc2Zvcm1hdGlvbiBvZiByZXNwb25zZSB2YXJpYWJsZSAoZ2FpbikKeS5sb2cuYXhpcyA9ICdsb2coR2FpbiknCmRmLmxvZyA9IGRhdGEuZnJhbWUoZGZbJ2RlbnNpdHknXSwgbG9nKGRmWydnYWluJ10pKQpwbG90KGRmLmxvZywgbWFpbj10aXRsZSwgeGxhYj14LmF4aXMsIHlsYWI9eS5sb2cuYXhpcywgeGxpbT14LnJhbmdlLCB5bGltPXkucmFuZ2UpCgoKIyBBdmVyYWdlIHJlcGxpY2F0ZSBtZWFzdXJlbWVudHMKZGYubG9nLmF2ZyA9IGFnZ3JlZ2F0ZShsaXN0KGdhaW49ZGYubG9nJGdhaW4pLCBieT1saXN0KGRlbnNpdHk9ZGYubG9nJGRlbnNpdHkpLCBGVU49bWVhbikKcGxvdChkZi5sb2cuYXZnLCBtYWluPXRpdGxlLCB4bGFiPXguYXhpcywgeWxhYj15LmxvZy5heGlzLCB4bGltPXgucmFuZ2UsIHlsaW09eS5yYW5nZSkKCgojIEZpdCBnYWluIHRvIGRlbnNpdHkKbGVhc3Quc3F1YXJlcyA8LSBsbShnYWlufmRlbnNpdHksIGRhdGE9ZGYubG9nLmF2ZykKbGFkIDwtIGxhZChnYWlufmRlbnNpdHksIGRhdGE9ZGYubG9nLmF2ZykKcXVhbnQgPC0gcnEoZ2Fpbn5kZW5zaXR5LCB0YXU9LjUsIGRhdGE9ZGYubG9nLmF2ZykKCnBsb3QoZGYubG9nLCBtYWluPXRpdGxlLCB4bGFiPXguYXhpcywgeWxhYj15LmxvZy5heGlzLCB4bGltPXgucmFuZ2UsIHlsaW09eS5yYW5nZSkKYWJsaW5lKGxlYXN0LnNxdWFyZXMsIGNvbD0ncmVkJykKYWJsaW5lKGxhZCwgY29sPSdibHVlJykKYWJsaW5lKHF1YW50LCBjb2w9J2dyZWVuJykKbGVnZW5kKCd0b3ByaWdodCcsIGxlZ2VuZD1jKCdMZWFzdCBTcXVhcmVzIFJlZ3Jlc3Npb24gTGluZScsICdMZWFzdCBBYnNvbHV0ZSBEZXZpYXRpb25zIFJlZ3Jlc3Npb24gTGluZScsICc1MCUgUXVhbnRpbGUgUmVncmVzc2lvbiBMaW5lJyksIGNvbD1jKCdyZWQnLCAnYmx1ZScsICdncmVlbicpLCBsdHk9MSkKCmMoY29yKGRmLmxvZy5hdmcpLCBzdW1tYXJ5KGxlYXN0LnNxdWFyZXMpJHIuc3F1YXJlZCkKbGVhc3Quc3F1YXJlcwpsYWQKcXVhbnQKCgojIENoZWNrIGNvbmRpdGlvbnMgZm9yIGxpbmVhciByZWdyZXNzaW9uOiBsaW5lYXJpdHksIG5vcm1hbGl0eSBvZiByZXNpZHVhbHMsIGFuZCBjb25zdGFudCB2YXJpYWJpbGl0eQpsZWFzdC5zcXVhcmVzLnJlc2lkdWFscyA8LSBkYXRhLmZyYW1lKGRmLmxvZ1snZGVuc2l0eSddLCBkZi5sb2dbJ2dhaW4nXSAtIHJlcChwcmVkaWN0KGxlYXN0LnNxdWFyZXMpLCBlYWNoPTEwKSkKbGFkLnJlc2lkdWFscyA8LSBkYXRhLmZyYW1lKGRmLmxvZ1snZGVuc2l0eSddLCBkZi5sb2dbJ2dhaW4nXSAtIHJlcChwcmVkaWN0KGxhZCksIGVhY2g9MTApKQpxdWFudC5yZXNpZHVhbHMgPC0gZGF0YS5mcmFtZShkZi5sb2dbJ2RlbnNpdHknXSwgZGYubG9nWydnYWluJ10gLSByZXAocHJlZGljdChxdWFudCksIGVhY2g9MTApKQoKdGl0bGUucmVzaWR1YWxzMSA8LSAnUmVzaWR1YWxzIG9mIExlYXN0IFNxdWFyZXMgUmVncmVzc2lvbiBMaW5lJwp0aXRsZS5yZXNpZHVhbHMyIDwtICdSZXNpZHVhbHMgb2YgTGVhc3QgQWJzb2x1dGUgRGV2aWF0aW9ucyBSZWdyZXNzaW9uIExpbmUnCnRpdGxlLnJlc2lkdWFsczMgPC0gJ1Jlc2lkdWFscyBvZiA1MCUgUXVhbnRpbGUgUmVncmVzc2lvbiBMaW5lJwpwbG90KGxlYXN0LnNxdWFyZXMucmVzaWR1YWxzJGdhaW4sIG1haW49dGl0bGUucmVzaWR1YWxzMSwgeWxhYj15LmF4aXMpCmFibGluZSgwLCAwLCBjb2w9J3JlZCcpCnBsb3QobGFkLnJlc2lkdWFscyRnYWluLCBtYWluPXRpdGxlLnJlc2lkdWFsczIsIHlsYWI9eS5heGlzKQphYmxpbmUoMCwgMCwgY29sPSdibHVlJykKcGxvdChxdWFudC5yZXNpZHVhbHMkZ2FpbiwgbWFpbj10aXRsZS5yZXNpZHVhbHMzLCB5bGFiPXkuYXhpcykKYWJsaW5lKDAsIDAsIGNvbD0nZ3JlZW4nKQoKbnVtLmJpbnMgPC0gMTIKaGlzdChsZWFzdC5zcXVhcmVzLnJlc2lkdWFscyRnYWluLCBicmVha3M9bnVtLmJpbnMsIG1haW49dGl0bGUucmVzaWR1YWxzMSwgeGxhYj15LmF4aXMsIGNvbD0ncmVkJykKaGlzdChsYWQucmVzaWR1YWxzJGdhaW4sIGJyZWFrcz1udW0uYmlucywgbWFpbj10aXRsZS5yZXNpZHVhbHMyLCB4bGFiPXkuYXhpcywgY29sPSdibHVlJykKaGlzdChxdWFudC5yZXNpZHVhbHMkZ2FpbiwgYnJlYWtzPW51bS5iaW5zLCBtYWluPXRpdGxlLnJlc2lkdWFsczMsIHhsYWI9eS5heGlzLCBjb2w9J2dyZWVuJykKCnFxbm9ybShsZWFzdC5zcXVhcmVzLnJlc2lkdWFscyRnYWluLCBtYWluPXBhc3RlKCdOb3JtYWwgUS1RIFBsb3Qgd2l0aCcsIHRpdGxlLnJlc2lkdWFsczEpLCBjZXgubWFpbj0xKQpxcWxpbmUobGVhc3Quc3F1YXJlcy5yZXNpZHVhbHMkZ2FpbiwgY29sPSdyZWQnKQpxcW5vcm0obGFkLnJlc2lkdWFscyRnYWluLCBtYWluPXBhc3RlKCdOb3JtYWwgUS1RIFBsb3Qgd2l0aCcsIHRpdGxlLnJlc2lkdWFsczIpLCBjZXgubWFpbj0xKQpxcWxpbmUobGFkLnJlc2lkdWFscyRnYWluLCBjb2w9J2JsdWUnKQpxcW5vcm0ocXVhbnQucmVzaWR1YWxzJGdhaW4sIG1haW49cGFzdGUoJ05vcm1hbCBRLVEgUGxvdCB3aXRoJywgdGl0bGUucmVzaWR1YWxzMyksIGNleC5tYWluPTEpCnFxbGluZShxdWFudC5yZXNpZHVhbHMkZ2FpbiwgY29sPSdncmVlbicpCmBgYAoKCiMjIFNjZW5hcmlvIDI6IFByZWRpY3RpbmcKVWx0aW1hdGVseSB3ZSBhcmUgaW50ZXJlc3RlZCBpbiBhbnN3ZXJpbmcgcXVlc3Rpb25zIHN1Y2ggYXM6IEdpdmVuIGEgZ2FpbiByZWFkaW5nIG9mIDM4LjYsIHdoYXQgaXMgdGhlIGRlbnNpdHkgb2YgdGhlIHNub3ctcGFjaz8gR2l2ZW4gYSBnYWluIHJlYWRpbmcgb2YgNDI2LjcsIHdoYXQgaXMgdGhlIGRlbnNpdHkgb2YgdGhlIHNub3ctcGFjaz8gVGhlc2UgdHdvIG51bWVyaWMgdmFsdWVzLCAzOC42IGFuZCA0MjYuNywgd2VyZSBjaG9zZW4gYmVjYXVzZSB0aGV5IGFyZSB0aGUgYXZlcmFnZSBnYWlucyBmb3IgdGhlIDAuNTA4IGFuZCAwLjAwMSBkZW5zaXRpZXMsIHJlc3BlY3RpdmVseS4KCiogRGV2ZWxvcCBhIHByb2NlZHVyZSBmb3IgYWRkaW5nIGJhbmRzIGFyb3VuZCB5b3VyIGxlYXN0IHNxdWFyZXMgbGluZSB0aGF0IGNhbiBiZSB1c2VkIHRvIG1ha2UgaW50ZXJ2YWwgZXN0aW1hdGVzIGZvciB0aGUgc25vdy1wYWNrIGRlbnNpdHkgZnJvbSBnYWluIG1lYXN1cmVtZW50cy4gS2VlcCBpbiBtaW5kIGhvdyB0aGUgZGF0YSB3ZXJlIGNvbGxlY3RlZDogc2V2ZXJhbCBtZWFzdXJlbWVudHMgb2YgZ2FpbiB3ZXJlIHRha2VuIGZvciBwb2x5ZW55dGh5bGVuZSBibG9ja3Mgb2Yga25vd24gZGVuc2l0eS4KYGBge3IgZmlnLmFzcD0yLCBmaWcud2lkdGg9NX0KIyBQcmVkaWN0aW9ucwpQcmVkaWN0TG9nR2FpbiA8LSBmdW5jdGlvbihkZW5zaXR5KQogIHByZWRpY3QobGVhc3Quc3F1YXJlcywgZGF0YS5mcmFtZShkZW5zaXR5PWRlbnNpdHkpKSAgIyBQcmVkaWN0IGxvZyhnYWluKSB1c2luZyBkZW5zaXR5CgpQcmVkaWN0RGVuc2l0eUxlYXN0U3F1YXJlcyA8LSBmdW5jdGlvbihnYWluKSB7CiAgaW50ZXJjZXB0IDwtIGNvZWYobGVhc3Quc3F1YXJlcylbWzFdXQogIHNsb3BlIDwtIGNvZWYobGVhc3Quc3F1YXJlcylbWzJdXQogIChsb2coZ2FpbikgLSBpbnRlcmNlcHQpIC8gc2xvcGUgICMgUHJlZGljdCBkZW5zaXR5IHVzaW5nIGdhaW4KfQoKUHJlZGljdERlbnNpdHlMYWQgPC0gZnVuY3Rpb24oZ2FpbikgewogIGludGVyY2VwdCA8LSBjb2VmKGxhZClbWzFdXQogIHNsb3BlIDwtIGNvZWYobGFkKVtbMl1dCiAgKGxvZyhnYWluKSAtIGludGVyY2VwdCkgLyBzbG9wZSAgIyBQcmVkaWN0IGRlbnNpdHkgdXNpbmcgZ2Fpbgp9CgpQcmVkaWN0RGVuc2l0eVF1YW50IDwtIGZ1bmN0aW9uKGdhaW4pIHsKICBpbnRlcmNlcHQgPC0gY29lZihxdWFudClbWzFdXQogIHNsb3BlIDwtIGNvZWYocXVhbnQpW1syXV0KICAobG9nKGdhaW4pIC0gaW50ZXJjZXB0KSAvIHNsb3BlICAjIFByZWRpY3QgZGVuc2l0eSB1c2luZyBnYWluCn0KCgojIDk1JSBwcmVkaWN0aW9uIGFuZCBjb25maWRlbmNlIGludGVydmFscyBvZiBsb2coZ2FpbikgdXNpbmcgZGVuc2l0eQp0IDwtIHF0KC45NzUsIGRmPW0tMikKbWVhbi5kZW5zaXR5IDwtIG1lYW4oZGYubG9nLmF2ZyRkZW5zaXR5KQpzdW1tYXRpb24gPC0gc3VtKChkZi5sb2cuYXZnJGRlbnNpdHkgLSBtZWFuLmRlbnNpdHkpIF4gMikKCnMyIDwtIGFnZ3JlZ2F0ZShsaXN0KHZhcmlhbmNlPWxlYXN0LnNxdWFyZXMucmVzaWR1YWxzJGdhaW4pLCBieT1saXN0KGRlbnNpdHk9bGVhc3Quc3F1YXJlcy5yZXNpZHVhbHMkZGVuc2l0eSksIEZVTj12YXIpCnMucG9vbGVkIDwtIHNxcnQobWVhbihzMiR2YXJpYW5jZSkpCgpjZW50ZXIuZXhwciA8LSBxdW90ZShjZW50ZXIgPC0gUHJlZGljdExvZ0dhaW4oZGVuc2l0eSkpCmNpLndpZHRoLmV4cHIgPC0gcXVvdGUod2lkdGggPC0gdCAqIHMucG9vbGVkICogc3FydCgxL20gKyAoZGVuc2l0eS1tZWFuLmRlbnNpdHkpXjIgLyBzdW1tYXRpb24pKQpwaS53aWR0aC5leHByIDwtIHF1b3RlKHdpZHRoIDwtIHQgKiBzLnBvb2xlZCAqIHNxcnQoMSArIDEvbSArIChkZW5zaXR5LW1lYW4uZGVuc2l0eSleMiAvIHN1bW1hdGlvbikpCgpMb2dHYWluQ2lMb3dlciA8LSBmdW5jdGlvbihkZW5zaXR5KSB7CiAgZXZhbChjZW50ZXIuZXhwcikKICBldmFsKGNpLndpZHRoLmV4cHIpCiAgY2VudGVyIC0gd2lkdGgKfQoKTG9nR2FpbkNpVXBwZXIgPC0gZnVuY3Rpb24oZGVuc2l0eSkgewogIGV2YWwoY2VudGVyLmV4cHIpCiAgZXZhbChjaS53aWR0aC5leHByKQogIGNlbnRlciArIHdpZHRoCn0KCkxvZ0dhaW5QaUxvd2VyIDwtIGZ1bmN0aW9uKGRlbnNpdHkpIHsKICBldmFsKGNlbnRlci5leHByKQogIGV2YWwocGkud2lkdGguZXhwcikKICBjZW50ZXIgLSB3aWR0aAp9CgpMb2dHYWluUGlVcHBlciA8LSBmdW5jdGlvbihkZW5zaXR5KSB7CiAgZXZhbChjZW50ZXIuZXhwcikKICBldmFsKHBpLndpZHRoLmV4cHIpCiAgY2VudGVyICsgd2lkdGgKfQoKCiMgQWRkIGJhbmRzIGFyb3VuZCBsZWFzdCBzcXVhcmVzIGxpbmUKcGxvdChkZi5sb2csIG1haW49dGl0bGUsIHhsYWI9eC5heGlzLCB5bGFiPXkubG9nLmF4aXMsIHhsaW09eC5yYW5nZSwgeWxpbT15LnJhbmdlKQphYmxpbmUobGVhc3Quc3F1YXJlcywgY29sPSdyZWQnKQoKY2kuY29sIDwtICdwdXJwbGUnCnBpLmNvbCA8LSAnYmx1ZScKc3ltYm9sIDwtICctJwpzaXplIDwtIDEuNQpsaW5lLnR5cGUgPC0gMwpsaW5lLndpZHRoIDwtIDAuNwoKY29uZmlkZW5jZS5pbnRlcnZhbHMgPC0gZGF0YS5mcmFtZShkZW5zaXR5PWRmLmxvZy5hdmckZGVuc2l0eSwgbG93ZXI9TG9nR2FpbkNpTG93ZXIoZGYubG9nLmF2ZyRkZW5zaXR5KSwgdXBwZXI9TG9nR2FpbkNpVXBwZXIoZGYubG9nLmF2ZyRkZW5zaXR5KSkKcG9pbnRzKHg9Y29uZmlkZW5jZS5pbnRlcnZhbHMkZGVuc2l0eSwgeT1jb25maWRlbmNlLmludGVydmFscyRsb3dlciwgY29sPWNpLmNvbCwgcGNoPXN5bWJvbCwgY2V4PXNpemUpCnBvaW50cyh4PWNvbmZpZGVuY2UuaW50ZXJ2YWxzJGRlbnNpdHksIHk9Y29uZmlkZW5jZS5pbnRlcnZhbHMkdXBwZXIsIGNvbD1jaS5jb2wsIHBjaD1zeW1ib2wsIGNleD1zaXplKQpsaW5lcyh4PWNvbmZpZGVuY2UuaW50ZXJ2YWxzJGRlbnNpdHksIHk9Y29uZmlkZW5jZS5pbnRlcnZhbHMkbG93ZXIsIGNvbD1jaS5jb2wsIGx0eT1saW5lLnR5cGUsIGx3ZD1saW5lLndpZHRoKQpsaW5lcyh4PWNvbmZpZGVuY2UuaW50ZXJ2YWxzJGRlbnNpdHksIHk9Y29uZmlkZW5jZS5pbnRlcnZhbHMkdXBwZXIsIGNvbD1jaS5jb2wsIGx0eT1saW5lLnR5cGUsIGx3ZD1saW5lLndpZHRoKQoKcHJlZGljdGlvbi5pbnRlcnZhbHMgPC0gZGF0YS5mcmFtZShkZW5zaXR5PWRmLmxvZy5hdmckZGVuc2l0eSwgbG93ZXI9TG9nR2FpblBpTG93ZXIoZGYubG9nLmF2ZyRkZW5zaXR5KSwgdXBwZXI9TG9nR2FpblBpVXBwZXIoZGYubG9nLmF2ZyRkZW5zaXR5KSkKcG9pbnRzKHg9cHJlZGljdGlvbi5pbnRlcnZhbHMkZGVuc2l0eSwgeT1wcmVkaWN0aW9uLmludGVydmFscyRsb3dlciwgY29sPXBpLmNvbCwgcGNoPXN5bWJvbCwgY2V4PXNpemUpCnBvaW50cyh4PXByZWRpY3Rpb24uaW50ZXJ2YWxzJGRlbnNpdHksIHk9cHJlZGljdGlvbi5pbnRlcnZhbHMkdXBwZXIsIGNvbD1waS5jb2wsIHBjaD1zeW1ib2wsIGNleD1zaXplKQpsaW5lcyh4PXByZWRpY3Rpb24uaW50ZXJ2YWxzJGRlbnNpdHksIHk9cHJlZGljdGlvbi5pbnRlcnZhbHMkbG93ZXIsIGNvbD1waS5jb2wsIGx0eT1saW5lLnR5cGUsIGx3ZD1saW5lLndpZHRoKQpsaW5lcyh4PXByZWRpY3Rpb24uaW50ZXJ2YWxzJGRlbnNpdHksIHk9cHJlZGljdGlvbi5pbnRlcnZhbHMkdXBwZXIsIGNvbD1waS5jb2wsIGx0eT1saW5lLnR5cGUsIGx3ZD1saW5lLndpZHRoKQoKbGVnZW5kKCd0b3ByaWdodCcsIGxlZ2VuZD1jKCdMZWFzdCBTcXVhcmVzIFJlZ3Jlc3Npb24gTGluZScsICc5NSUgQ29uZmlkZW5jZSBJbnRlcnZhbCBCYW5kcycsICc5NSUgUHJlZGljdGlvbiBJbnRlcnZhbCBCYW5kcycpLCBjb2w9YygncmVkJywgY2kuY29sLCBwaS5jb2wpLCBsdHk9MSkKCgojIDk1JSBwcmVkaWN0aW9uIGFuZCBjb25maWRlbmNlIGludGVydmFscyBvZiBkZW5zaXR5IHVzaW5nIGdhaW4KZW5kLnBvaW50cyA8LSBjKC0xLCAzKSAgIyBJbnRlcnZhbCB0byBzZWFyY2ggdGhlIHJvb3QgaW4KCkRlbnNpdHlDaSA8LSBmdW5jdGlvbihnYWluKSB7CiAgbG93ZXIgPC0gdW5pcm9vdChmdW5jdGlvbihkZW5zaXR5KSBsb2coZ2FpbikgLSBMb2dHYWluQ2lMb3dlcihkZW5zaXR5KSwgaW50ZXJ2YWw9ZW5kLnBvaW50cylbWzFdXQogIHVwcGVyIDwtIHVuaXJvb3QoZnVuY3Rpb24oZGVuc2l0eSkgbG9nKGdhaW4pIC0gTG9nR2FpbkNpVXBwZXIoZGVuc2l0eSksIGludGVydmFsPWVuZC5wb2ludHMpW1sxXV0KICBjKGxvd2VyLCB1cHBlcikKfQoKRGVuc2l0eVBpIDwtIGZ1bmN0aW9uKGdhaW4pIHsKICBsb3dlciA8LSB1bmlyb290KGZ1bmN0aW9uKGRlbnNpdHkpIGxvZyhnYWluKSAtIExvZ0dhaW5QaUxvd2VyKGRlbnNpdHkpLCBlbmQucG9pbnRzKVtbMV1dCiAgdXBwZXIgPC0gdW5pcm9vdChmdW5jdGlvbihkZW5zaXR5KSBsb2coZ2FpbikgLSBMb2dHYWluUGlVcHBlcihkZW5zaXR5KSwgZW5kLnBvaW50cylbWzFdXQogIGMobG93ZXIsIHVwcGVyKQp9CgoKIyBQb2ludCBhbmQgaW50ZXJ2YWwgZXN0aW1hdGVzIGZvciBleGFtcGxlIGdhaW4gcmVhZGluZ3MKUHJlZGljdERlbnNpdHlMZWFzdFNxdWFyZXMoMzguNikgICMgMzguNiBpcyB0aGUgYXZlcmFnZSBnYWluIGZvciAwLjUwOCBkZW5zaXR5ClByZWRpY3REZW5zaXR5TGFkKDM4LjYpClByZWRpY3REZW5zaXR5UXVhbnQoMzguNikKRGVuc2l0eUNpKDM4LjYpCkRlbnNpdHlQaSgzOC42KQoKUHJlZGljdERlbnNpdHlMZWFzdFNxdWFyZXMoNDI2LjcpICAjIDQyNi43IGlzIHRoZSBhdmVyYWdlIGdhaW4gZm9yIDAuMDAxIGRlbnNpdHkKUHJlZGljdERlbnNpdHlMYWQoNDI2LjcpClByZWRpY3REZW5zaXR5UXVhbnQoMzguNikKRGVuc2l0eUNpKDQyNi43KQpEZW5zaXR5UGkoNDI2LjcpCmBgYAoKCiMjIFNjZW5hcmlvIDM6IENyb3NzLVZhbGlkYXRpb24KVG8gY2hlY2sgaG93IHdlbGwgeW91ciBwcm9jZWR1cmUgd29ya3MsIG9taXQgdGhlIHNldCBvZiBtZWFzdXJlbWVudHMgY29ycmVzcG9uZGluZyB0byB0aGUgYmxvY2sgb2YgZGVuc2l0eSAwLjUwOCwgYXBwbHkgeW91ciAiZXN0aW1hdGlvbiIvY2FsaWJyYXRpb24gcHJvY2VkdXJlIHRvIHRoZSByZW1haW5pbmcgZGF0YSwgYW5kIHByb3ZpZGUgYW4gaW50ZXJ2YWwgZXN0aW1hdGUgZm9yIHRoZSBkZW5zaXR5IG9mIGEgYmxvY2sgd2l0aCBhbiBhdmVyYWdlIHJlYWRpbmcgb2YgMzguNi4gV2hlcmUgZG9lcyB0aGUgYWN0dWFsIGRlbnNpdHkgZmFsbCBpbiB0aGUgaW50ZXJ2YWw/IFRyeSB0aGUgc2FtZSB0ZXN0LCBmb3IgdGhlIHNldCBvZiBtZWFzdXJlbWVudHMgYXQgdGhlIDAuMDAxIGRlbnNpdHkuCmBgYHtyIGZpZy5hc3A9MiwgZmlnLndpZHRoPTV9CmZvciAob21pdHRlZCBpbiBjKDAuNTA4LCAwLjAwMSkpIHsKICAjIE9taXQgbWVhc3VyZW1lbnRzIGNvcnJlc3BvbmRpbmcgdG8gdGhlIHNwZWNpZmllZCBkZW5zaXR5CiAgZGYubG9nLm9taXR0ZWQgPSBkZi5sb2dbd2hpY2goZGYubG9nWydkZW5zaXR5J10gIT0gb21pdHRlZCksIF0KICBkZi5sb2cuYXZnLm9taXR0ZWQgPC0gZGYubG9nLmF2Z1t3aGljaChkZi5sb2cuYXZnWydkZW5zaXR5J10gIT0gb21pdHRlZCksIF0KICAKICAKICAjIFJlZG8gY2FsY3VsYXRpb25zIHVzaW5nIG1vZGlmaWVkIGRhdGFzZXQKICBsZWFzdC5zcXVhcmVzIDwtIGxtKGdhaW5+ZGVuc2l0eSwgZGF0YT1kZi5sb2cuYXZnLm9taXR0ZWQpCiAgCiAgbWVhbi5kZW5zaXR5IDwtIG1lYW4oZGYubG9nLmF2Zy5vbWl0dGVkJGRlbnNpdHkpCiAgc3VtbWF0aW9uIDwtIHN1bSgoZGYubG9nLmF2Zy5vbWl0dGVkJGRlbnNpdHkgLSBtZWFuLmRlbnNpdHkpIF4gMikKICAKICBzMiA8LSBhZ2dyZWdhdGUobGlzdCh2YXJpYW5jZT1sZWFzdC5zcXVhcmVzLnJlc2lkdWFscyRnYWluKSwgYnk9bGlzdChkZW5zaXR5PWxlYXN0LnNxdWFyZXMucmVzaWR1YWxzJGRlbnNpdHkpLCBGVU49dmFyKQogIHMucG9vbGVkIDwtIHNxcnQobWVhbihzMiR2YXJpYW5jZSkpCiAgCiAgY2kud2lkdGguZXhwciA8LSBxdW90ZSh3aWR0aCA8LSB0ICogcy5wb29sZWQgKiBzcXJ0KDEvKG0tMSkgKyAoZGVuc2l0eS1tZWFuLmRlbnNpdHkpXjIgLyBzdW1tYXRpb24pKQogIHBpLndpZHRoLmV4cHIgPC0gcXVvdGUod2lkdGggPC0gdCAqIHMucG9vbGVkICogc3FydCgxICsgMS8obS0xKSArIChkZW5zaXR5LW1lYW4uZGVuc2l0eSleMiAvIHN1bW1hdGlvbikpCiAgCiAgcGxvdChkZi5sb2cub21pdHRlZCwgbWFpbj10aXRsZSwgeGxhYj14LmF4aXMsIHlsYWI9eS5sb2cuYXhpcywgeGxpbT14LnJhbmdlLCB5bGltPXkucmFuZ2UpCiAgYWJsaW5lKGxlYXN0LnNxdWFyZXMsIGNvbD0ncmVkJykKICAKICBjaS5jb2wgPC0gJ3B1cnBsZScKICBwaS5jb2wgPC0gJ2JsdWUnCiAgc3ltYm9sIDwtICctJwogIHNpemUgPC0gMS41CiAgbGluZS50eXBlIDwtIDMKICBsaW5lLndpZHRoIDwtIDAuNwogIAogIGNvbmZpZGVuY2UuaW50ZXJ2YWxzIDwtIGRhdGEuZnJhbWUoZGVuc2l0eT1kZi5sb2cuYXZnLm9taXR0ZWQkZGVuc2l0eSwgbG93ZXI9TG9nR2FpbkNpTG93ZXIoZGYubG9nLmF2Zy5vbWl0dGVkJGRlbnNpdHkpLCB1cHBlcj1Mb2dHYWluQ2lVcHBlcihkZi5sb2cuYXZnLm9taXR0ZWQkZGVuc2l0eSkpCiAgcG9pbnRzKHg9Y29uZmlkZW5jZS5pbnRlcnZhbHMkZGVuc2l0eSwgeT1jb25maWRlbmNlLmludGVydmFscyRsb3dlciwgY29sPWNpLmNvbCwgcGNoPXN5bWJvbCwgY2V4PXNpemUpCiAgcG9pbnRzKHg9Y29uZmlkZW5jZS5pbnRlcnZhbHMkZGVuc2l0eSwgeT1jb25maWRlbmNlLmludGVydmFscyR1cHBlciwgY29sPWNpLmNvbCwgcGNoPXN5bWJvbCwgY2V4PXNpemUpCiAgbGluZXMoeD1jb25maWRlbmNlLmludGVydmFscyRkZW5zaXR5LCB5PWNvbmZpZGVuY2UuaW50ZXJ2YWxzJGxvd2VyLCBjb2w9Y2kuY29sLCBsdHk9bGluZS50eXBlLCBsd2Q9bGluZS53aWR0aCkKICBsaW5lcyh4PWNvbmZpZGVuY2UuaW50ZXJ2YWxzJGRlbnNpdHksIHk9Y29uZmlkZW5jZS5pbnRlcnZhbHMkdXBwZXIsIGNvbD1jaS5jb2wsIGx0eT1saW5lLnR5cGUsIGx3ZD1saW5lLndpZHRoKQogIAogIHByZWRpY3Rpb24uaW50ZXJ2YWxzIDwtIGRhdGEuZnJhbWUoZGVuc2l0eT1kZi5sb2cuYXZnLm9taXR0ZWQkZGVuc2l0eSwgbG93ZXI9TG9nR2FpblBpTG93ZXIoZGYubG9nLmF2Zy5vbWl0dGVkJGRlbnNpdHkpLCB1cHBlcj1Mb2dHYWluUGlVcHBlcihkZi5sb2cuYXZnLm9taXR0ZWQkZGVuc2l0eSkpCiAgcG9pbnRzKHg9cHJlZGljdGlvbi5pbnRlcnZhbHMkZGVuc2l0eSwgeT1wcmVkaWN0aW9uLmludGVydmFscyRsb3dlciwgY29sPXBpLmNvbCwgcGNoPXN5bWJvbCwgY2V4PXNpemUpCiAgcG9pbnRzKHg9cHJlZGljdGlvbi5pbnRlcnZhbHMkZGVuc2l0eSwgeT1wcmVkaWN0aW9uLmludGVydmFscyR1cHBlciwgY29sPXBpLmNvbCwgcGNoPXN5bWJvbCwgY2V4PXNpemUpCiAgbGluZXMoeD1wcmVkaWN0aW9uLmludGVydmFscyRkZW5zaXR5LCB5PXByZWRpY3Rpb24uaW50ZXJ2YWxzJGxvd2VyLCBjb2w9cGkuY29sLCBsdHk9bGluZS50eXBlLCBsd2Q9bGluZS53aWR0aCkKICBsaW5lcyh4PXByZWRpY3Rpb24uaW50ZXJ2YWxzJGRlbnNpdHksIHk9cHJlZGljdGlvbi5pbnRlcnZhbHMkdXBwZXIsIGNvbD1waS5jb2wsIGx0eT1saW5lLnR5cGUsIGx3ZD1saW5lLndpZHRoKQogIAogIGxlZ2VuZCgndG9wcmlnaHQnLCBsZWdlbmQ9YygnTGVhc3QgU3F1YXJlcyBSZWdyZXNzaW9uIExpbmUnLCAnOTUlIENvbmZpZGVuY2UgSW50ZXJ2YWwgQmFuZHMnLCAnOTUlIFByZWRpY3Rpb24gSW50ZXJ2YWwgQmFuZHMnKSwgY29sPWMoJ3JlZCcsIGNpLmNvbCwgcGkuY29sKSwgbHR5PTEpCiAgCiAgcHJpbnQoUHJlZGljdERlbnNpdHlMZWFzdFNxdWFyZXMoMzguNikpICAjIDM4LjYgaXMgdGhlIGF2ZXJhZ2UgZ2FpbiBmb3IgMC41MDggZGVuc2l0eQogIHByaW50KERlbnNpdHlDaSgzOC42KSkKICBwcmludChEZW5zaXR5UGkoMzguNikpCiAgCiAgcHJpbnQoUHJlZGljdERlbnNpdHlMZWFzdFNxdWFyZXMoNDI2LjcpKSAgIyA0MjYuNyBpcyB0aGUgYXZlcmFnZSBnYWluIGZvciAwLjAwMSBkZW5zaXR5CiAgcHJpbnQoRGVuc2l0eUNpKDQyNi43KSkKICBwcmludChEZW5zaXR5UGkoNDI2LjcpKQp9CmBgYAoKCiMjIEFkZGl0aW9uYWwgU2NlbmFyaW86IFRlbXBlcmF0dXJlLCBET1ksIGFuZCBMYXRpdHVkZS4KVXNlIHRoZSBhZGRpdGlvbmFsIGRhdGFzZXQgdG8gY29uc3RydWN0IGEgbW9kZWwgZml0dGluZyB0ZW1wZXJhdHVyZSB3aXRoIERPWSwgbGF0aXR1ZGUsIGFuZCBvdGhlciByZWFzb25hYmxlIGZlYXR1cmVzLiBUcnkgc2tldGNoaW5nIHRoZSBsZWFzdCBzcXVhcmVzIGxpbmUgb24gYSBzY2F0dGVyIHBsb3QuIFdlIGFpbSB0byBpbnZlc3RpZ2F0ZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGVtcGVyYXR1cmUgYW5kIHRoZSBET1ksIGFuZCBpdHMgbGF0aXR1ZGUuCmBgYHtyfQojIENoZWNrIHRoZSBjb3JyZWxhdGlvbgpkYXRhIDwtIHJlYWQuY3N2KCdGdWxsIFJlc29sdXRpb24gRGF0YS82NDUwNjQyMC5jc3YnLCBoZWFkZXI9VFJVRSkKZGF0YSA8LSBkYXRhWyxjKCdIb3VyJywnRE9ZJywnUE9TX0RPWScsJ0xhdCcsJ0xvbicsJ1RzJywnQlAnKV0KCiMgRHJvcCB0aGUgZXh0cmVtZSBvdXRsaWVyIGNhc2UKI2RhdGEgPC0gZGF0YVt3aGljaChkYXRhJFRzPi0yMDApLF0KZGF0YV9tYXRyaXggPC0gYXMubWF0cml4KGRhdGEpCgojIENvcnJlbGF0aW9uIE1hdHJpeApjb3JyX21hdHJpeCA8LSBjb3IoZGF0YV9tYXRyaXgpCmNvcnJfbWF0cml4CmBgYAoKYGBge3J9CiMgR3JvdXAgYnkgRE9ZIGFuZCBhdmVyYWdlIHJlcGxpY2F0ZWQgbWVhc3VyZW1lbnRzCmRhdGEkRE9ZIDwtIHJvdW5kKGRhdGEkRE9ZLDApCmRhdGEuYXZnID0gYWdncmVnYXRlKGxpc3QoZGF0YT1kYXRhWyxjKCdUcycsJ0xhdCcpXSksIGJ5PWxpc3QoRE9ZPWRhdGEkRE9ZKSwgRlVOPW1lYW4pCgojIGxlYXN0IHNxdWFyZXMgbGluZQpnZ3Bsb3QoZGF0YS5hdmcsYWVzKHg9ZGF0YS5hdmckRE9ZLCB5PWRhdGEuYXZnJGRhdGEuVHMpKSArIAogIGdlb21fcG9pbnQoY29sb3I9JyMyOTgwQjknLCBzaXplID0gNCkgKyAKICBnZW9tX3Ntb290aChtZXRob2Q9bG0sIGNvbG9yPScjMkMzRTUwJykgK2dndGl0bGUobGFiZWwgPSJMZWFzdCBTcXVhcmVzIFJlZ3Jlc3Npb24gTGluZSIpICsgeGxhYigiRGF5IE9mIFllYXIiKSArCiAgeWxhYigiVGVtcGVyYXR1cmUiKQpmaXQxPC1sbShmb3JtdWxhID0gZGF0YS5UcyB+IERPWSwgZGF0YSA9IGRhdGEuYXZnKQpzdW1tYXJ5KGZpdDEpCgpnZ3Bsb3QoZGF0YS5hdmcsYWVzKHg9ZGF0YS5hdmckZGF0YS5MYXQsIHk9ZGF0YS5hdmckZGF0YS5UcykpICsgCiAgZ2VvbV9wb2ludChjb2xvcj0nIzI5ODBCOScsIHNpemUgPSA0KSArIAogIGdlb21fc21vb3RoKG1ldGhvZD1sbSwgY29sb3I9JyMyQzNFNTAnKSArZ2d0aXRsZShsYWJlbCA9IkxlYXN0IFNxdWFyZXMgUmVncmVzc2lvbiBMaW5lIikrIHhsYWIoIkxhdHRpdHVkZSIpICsKICB5bGFiKCJUZW1wZXJhdHVyZSIpCmZpdDI8LWxtKGZvcm11bGEgPSBkYXRhLlRzIH4gZGF0YS5MYXQsIGRhdGEgPSBkYXRhLmF2ZykKc3VtbWFyeShmaXQyKQoKIyBQb2x5bm9taWFsIFJlZ3Jlc3Npb24gTGluZQpmaXQzPC1sbShmb3JtdWxhID0gZGF0YS5UcyB+IERPWSArIGRhdGEuTGF0LCBkYXRhID0gZGF0YS5hdmcpCnN1bW1hcnkoZml0MykKCnFxbm9ybShmaXQyJHJlc2lkdWFscywgbWFpbj1wYXN0ZSgnTm9ybWFsIFEtUSBQbG90IHdpdGgnLCB0aXRsZS5yZXNpZHVhbHMxKSwgY2V4Lm1haW49MSkKcXFsaW5lKGZpdDIkcmVzaWR1YWxzLCBjb2w9J3JlZCcpCgp0aXRsZS5yZXNpZHVhbHMxIDwtICdSZXNpZHVhbHMgb2YgTGVhc3QgU3F1YXJlIFJlZ3Jlc3Npb24gTGluZScKcGxvdChmaXQyJHJlc2lkdWFscywgbWFpbj10aXRsZS5yZXNpZHVhbHMxLCB5bGFiID0gIlN0YW5kYXJkaXplZCBSZXNpZHVhbHMiKQphYmxpbmUoMCwgMCwgY29sPSdyZWQnKQoKYGBgCg==
=======
<<<<<<< HEAD
LS0tCnRpdGxlOiAnQ0FTRSBTVFVEWSA0OicKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKVGhpcyBzdHVkeSBhbGxvd3MgdXMgdG8gcmV2aXNpdC9yZW5ldwoKMS4gUmVncmVzc2lvbiBtb2RlbGluZwoyLiBQcm9wZXJ0aWVzIG9mIExlYXN0IFNxdWFyZXMvRml0dGluZyAiYSBsaW5lIgozLiBNdWx0aXBsZSBvYnNlcnZhdGlvbgoKRGF0YXNldHMgZm9yIHRoaXMgc3R1ZHkgYXJlCgoxLiBUaGUgbWFpbiBmaWxlOiBnYXVnZS50eHQKMi4gU3VwcGxlbWVudGFyeSBsYXJnZS1zY2FsZSBmaWxlczogZG93bmxvYWQgdGhlIGZvbGxvd2luZyBmb2xkZXIgRnVsbCBSZXNvbHV0aW9uIERhdGEuemlwIE1vcmUgaW5mb3JtYXRpb24gYWJvdXQgdGhlIHN1cHBsZW1lbnRhcnkgZmlsZSBjYW4gYmUgZm91bmQgYXQgaHR0cDovL2lhYnAuYXBsLndhc2hpbmd0b24uZWR1L2RhdGEuaHRtbCBhcyB3ZWxsIGFzIGh0dHA6Ly9uc2lkYy5vcmcvZGF0YS9HMDA3OTEKCgojIyBRdWVzdGlvbgpUaGUgYWltIG9mIHRoaXMgbGFiIGlzIHRvIHByb3ZpZGUgYSBzaW1wbGUgcHJvY2VkdXJlIGZvciBjb252ZXJ0aW5nIGdhaW4gaW50byBkZW5zaXR5IHdoZW4gdGhlIGdhdWdlIGlzIGluIG9wZXJhdGlvbi4gS2VlcCBpbiBtaW5kIHRoYXQgdGhlIGV4cGVyaW1lbnQgd2FzIGNvbmR1Y3RlZCBieSB2YXJ5aW5nIGRlbnNpdHkgYW5kIG1lYXN1cmluZyB0aGUgcmVzcG9uc2UgaW4gZ2FpbiwgYnV0IHdoZW4gdGhlIGdhdWdlIGlzIHVsdGltYXRlbHkgaW4gdXNlLCB0aGUgc25vdy1wYWNrIGRlbnNpdHkgaXMgdG8gYmUgZXN0aW1hdGVkIGZyb20gdGhlIG1lYXN1cmVkIGdhaW4uCgoKIyMgU2V0dXAKYGBge3J9CmRmIDwtIHJlYWQudGFibGUoJ2dhdWdlLTF3YjF3YTYtMmdwZWw0MS50eHQnLCBoZWFkZXI9VFJVRSkKZGYgPC0gZGZbb3JkZXIoZGYkZGVuc2l0eSksIF0gICMgU29ydCBmcm9tIGxlYXN0IHRvIGdyZWF0ZXN0IGRlbnNpdHkKCm0gPC0gOSAgIyBOdW1iZXIgb2YgZGlzdGluY3QgYmxvY2sgZGVuc2l0aWVzCnQgPC0gMTAgICMgTnVtYmVyIG9mIHJlcGxpY2F0ZSBtZWFzdXJlbWVudHMKCiNpbnN0YWxsLnBhY2thZ2VzKCdMMXBhY2snKQojaW5zdGFsbC5wYWNrYWdlcygicXVhbnRyZWciKQpsaWJyYXJ5KEwxcGFjaykgICMgVXNlZCBmb3IgbGVhc3QgYWJzb2x1dGUgZGV2aWF0aW9ucyByZWdyZXNzaW9uIGxpbmUKbGlicmFyeShxdWFudHJlZykgICMgVXNlZCBmb3IgcXVhbnRpbGUgcmVncmVzc2lvbiBsaW5lCmBgYAoKCiMjIFNjZW5hcmlvIDE6IEZpdHRpbmcKVXNlIHRoZSBkYXRhIHRvIGZpdCB0aGUgZ2Fpbiwgb3IgYSB0cmFuc2Zvcm1hdGlvbiBvZiBnYWluLCB0byBkZW5zaXR5LiBUcnkgc2tldGNoaW5nIHRoZSBsZWFzdCBzcXVhcmVzIGxpbmUgb24gYSBzY2F0dGVyIHBsb3QuCgoqIERvIHRoZSByZXNpZHVhbHMgaW5kaWNhdGUgYW55IHByb2JsZW1zIHdpdGggdGhlIGZpdD8KKiBJZiB0aGUgZGVuc2l0aWVzIG9mIHRoZSBwb2x5ZXRoeWxlbmUgYmxvY2tzIGFyZSBub3QgcmVwb3J0ZWQgZXhhY3RseSwgaG93IG1pZ2h0IHRoaXMgYWZmZWN0IHRoZSBmaXQ/CiogV2hhdCBpZiB0aGUgYmxvY2tzIG9mIHBvbHlldGh5bGVuZSB3ZXJlIG5vdCBtZWFzdXJlZCBpbiByYW5kb20gb3JkZXIgKGxvY2F0aW9uKT8KYGBge3J9CiMgUGxvdCByYXcgZGF0YQp0aXRsZSA8LSAnRGVuc2l0eSB2cy4gR2FpbicKeC5heGlzIDwtIGV4cHJlc3Npb24oJ0RlbnNpdHkgKGcvY20nXjMqJyknKQp5LmF4aXMgPC0gJ0dhaW4nCngucmFuZ2UgPC0gYygwLCAuNykKeS5yYW5nZSA8LSBjKDIuNSwgNikKcGxvdChkZiwgbWFpbj10aXRsZSwgeGxhYj14LmF4aXMsIHlsYWI9eS5heGlzLCB4bGltPXgucmFuZ2UpCgoKIyBUYWtlIGxvZyB0cmFuc2Zvcm1hdGlvbiBvZiByZXNwb25zZSB2YXJpYWJsZSAoZ2FpbikKeS5sb2cuYXhpcyA9ICdsb2coR2FpbiknCmRmLmxvZyA9IGRhdGEuZnJhbWUoZGZbJ2RlbnNpdHknXSwgbG9nKGRmWydnYWluJ10pKQpwbG90KGRmLmxvZywgbWFpbj10aXRsZSwgeGxhYj14LmF4aXMsIHlsYWI9eS5sb2cuYXhpcywgeGxpbT14LnJhbmdlLCB5bGltPXkucmFuZ2UpCgoKIyBBdmVyYWdlIHJlcGxpY2F0ZSBtZWFzdXJlbWVudHMKZGYubG9nLmF2ZyA9IGFnZ3JlZ2F0ZShsaXN0KGdhaW49ZGYubG9nJGdhaW4pLCBieT1saXN0KGRlbnNpdHk9ZGYubG9nJGRlbnNpdHkpLCBGVU49bWVhbikKcGxvdChkZi5sb2cuYXZnLCBtYWluPXRpdGxlLCB4bGFiPXguYXhpcywgeWxhYj15LmxvZy5heGlzLCB4bGltPXgucmFuZ2UsIHlsaW09eS5yYW5nZSkKCgojIEZpdCBnYWluIHRvIGRlbnNpdHkKbGVhc3Quc3F1YXJlcyA8LSBsbShnYWlufmRlbnNpdHksIGRhdGE9ZGYubG9nLmF2ZykKbGFkIDwtIGxhZChnYWlufmRlbnNpdHksIGRhdGE9ZGYubG9nLmF2ZykKcXVhbnQgPC0gcnEoZ2Fpbn5kZW5zaXR5LCB0YXU9LjUsIGRhdGE9ZGYubG9nLmF2ZykKCnBsb3QoZGYubG9nLCBtYWluPXRpdGxlLCB4bGFiPXguYXhpcywgeWxhYj15LmxvZy5heGlzLCB4bGltPXgucmFuZ2UsIHlsaW09eS5yYW5nZSkKYWJsaW5lKGxlYXN0LnNxdWFyZXMsIGNvbD0ncmVkJykKYWJsaW5lKGxhZCwgY29sPSdibHVlJykKYWJsaW5lKHF1YW50LCBjb2w9J2dyZWVuJykKbGVnZW5kKCd0b3ByaWdodCcsIGxlZ2VuZD1jKCdMZWFzdCBTcXVhcmVzIFJlZ3Jlc3Npb24gTGluZScsICdMZWFzdCBBYnNvbHV0ZSBEZXZpYXRpb25zIFJlZ3Jlc3Npb24gTGluZScsICc1MCUgUXVhbnRpbGUgUmVncmVzc2lvbiBMaW5lJyksIGNvbD1jKCdyZWQnLCAnYmx1ZScsICdncmVlbicpLCBsdHk9MSkKCmMoY29yKGRmLmxvZy5hdmcpLCBzdW1tYXJ5KGxlYXN0LnNxdWFyZXMpJHIuc3F1YXJlZCkKbGVhc3Quc3F1YXJlcwpsYWQKcXVhbnQKCgojIENoZWNrIGNvbmRpdGlvbnMgZm9yIGxpbmVhciByZWdyZXNzaW9uOiBsaW5lYXJpdHksIG5vcm1hbGl0eSBvZiByZXNpZHVhbHMsIGFuZCBjb25zdGFudCB2YXJpYWJpbGl0eQpsZWFzdC5zcXVhcmVzLnJlc2lkdWFscyA8LSBkYXRhLmZyYW1lKGRmLmxvZ1snZGVuc2l0eSddLCBkZi5sb2dbJ2dhaW4nXSAtIHJlcChwcmVkaWN0KGxlYXN0LnNxdWFyZXMpLCBlYWNoPTEwKSkKbGFkLnJlc2lkdWFscyA8LSBkYXRhLmZyYW1lKGRmLmxvZ1snZGVuc2l0eSddLCBkZi5sb2dbJ2dhaW4nXSAtIHJlcChwcmVkaWN0KGxhZCksIGVhY2g9MTApKQpxdWFudC5yZXNpZHVhbHMgPC0gZGF0YS5mcmFtZShkZi5sb2dbJ2RlbnNpdHknXSwgZGYubG9nWydnYWluJ10gLSByZXAocHJlZGljdChxdWFudCksIGVhY2g9MTApKQoKdGl0bGUucmVzaWR1YWxzMSA8LSAnUmVzaWR1YWxzIG9mIExlYXN0IFNxdWFyZXMgUmVncmVzc2lvbiBMaW5lJwp0aXRsZS5yZXNpZHVhbHMyIDwtICdSZXNpZHVhbHMgb2YgTGVhc3QgQWJzb2x1dGUgRGV2aWF0aW9ucyBSZWdyZXNzaW9uIExpbmUnCnRpdGxlLnJlc2lkdWFsczMgPC0gJ1Jlc2lkdWFscyBvZiA1MCUgUXVhbnRpbGUgUmVncmVzc2lvbiBMaW5lJwpwbG90KGxlYXN0LnNxdWFyZXMucmVzaWR1YWxzJGdhaW4sIG1haW49dGl0bGUucmVzaWR1YWxzMSwgeWxhYj15LmF4aXMpCmFibGluZSgwLCAwLCBjb2w9J3JlZCcpCnBsb3QobGFkLnJlc2lkdWFscyRnYWluLCBtYWluPXRpdGxlLnJlc2lkdWFsczIsIHlsYWI9eS5heGlzKQphYmxpbmUoMCwgMCwgY29sPSdibHVlJykKcGxvdChxdWFudC5yZXNpZHVhbHMkZ2FpbiwgbWFpbj10aXRsZS5yZXNpZHVhbHMzLCB5bGFiPXkuYXhpcykKYWJsaW5lKDAsIDAsIGNvbD0nZ3JlZW4nKQoKbnVtLmJpbnMgPC0gMTIKaGlzdChsZWFzdC5zcXVhcmVzLnJlc2lkdWFscyRnYWluLCBicmVha3M9bnVtLmJpbnMsIG1haW49dGl0bGUucmVzaWR1YWxzMSwgeGxhYj15LmF4aXMsIGNvbD0ncmVkJykKaGlzdChsYWQucmVzaWR1YWxzJGdhaW4sIGJyZWFrcz1udW0uYmlucywgbWFpbj10aXRsZS5yZXNpZHVhbHMyLCB4bGFiPXkuYXhpcywgY29sPSdibHVlJykKaGlzdChxdWFudC5yZXNpZHVhbHMkZ2FpbiwgYnJlYWtzPW51bS5iaW5zLCBtYWluPXRpdGxlLnJlc2lkdWFsczMsIHhsYWI9eS5heGlzLCBjb2w9J2dyZWVuJykKCnFxbm9ybShsZWFzdC5zcXVhcmVzLnJlc2lkdWFscyRnYWluLCBtYWluPXBhc3RlKCdOb3JtYWwgUS1RIFBsb3Qgd2l0aCcsIHRpdGxlLnJlc2lkdWFsczEpLCBjZXgubWFpbj0xKQpxcWxpbmUobGVhc3Quc3F1YXJlcy5yZXNpZHVhbHMkZ2FpbiwgY29sPSdyZWQnKQpxcW5vcm0obGFkLnJlc2lkdWFscyRnYWluLCBtYWluPXBhc3RlKCdOb3JtYWwgUS1RIFBsb3Qgd2l0aCcsIHRpdGxlLnJlc2lkdWFsczIpLCBjZXgubWFpbj0xKQpxcWxpbmUobGFkLnJlc2lkdWFscyRnYWluLCBjb2w9J2JsdWUnKQpxcW5vcm0ocXVhbnQucmVzaWR1YWxzJGdhaW4sIG1haW49cGFzdGUoJ05vcm1hbCBRLVEgUGxvdCB3aXRoJywgdGl0bGUucmVzaWR1YWxzMyksIGNleC5tYWluPTEpCnFxbGluZShxdWFudC5yZXNpZHVhbHMkZ2FpbiwgY29sPSdncmVlbicpCmBgYAoKCiMjIFNjZW5hcmlvIDI6IFByZWRpY3RpbmcKVWx0aW1hdGVseSB3ZSBhcmUgaW50ZXJlc3RlZCBpbiBhbnN3ZXJpbmcgcXVlc3Rpb25zIHN1Y2ggYXM6IEdpdmVuIGEgZ2FpbiByZWFkaW5nIG9mIDM4LjYsIHdoYXQgaXMgdGhlIGRlbnNpdHkgb2YgdGhlIHNub3ctcGFjaz8gR2l2ZW4gYSBnYWluIHJlYWRpbmcgb2YgNDI2LjcsIHdoYXQgaXMgdGhlIGRlbnNpdHkgb2YgdGhlIHNub3ctcGFjaz8gVGhlc2UgdHdvIG51bWVyaWMgdmFsdWVzLCAzOC42IGFuZCA0MjYuNywgd2VyZSBjaG9zZW4gYmVjYXVzZSB0aGV5IGFyZSB0aGUgYXZlcmFnZSBnYWlucyBmb3IgdGhlIDAuNTA4IGFuZCAwLjAwMSBkZW5zaXRpZXMsIHJlc3BlY3RpdmVseS4KCiogRGV2ZWxvcCBhIHByb2NlZHVyZSBmb3IgYWRkaW5nIGJhbmRzIGFyb3VuZCB5b3VyIGxlYXN0IHNxdWFyZXMgbGluZSB0aGF0IGNhbiBiZSB1c2VkIHRvIG1ha2UgaW50ZXJ2YWwgZXN0aW1hdGVzIGZvciB0aGUgc25vdy1wYWNrIGRlbnNpdHkgZnJvbSBnYWluIG1lYXN1cmVtZW50cy4gS2VlcCBpbiBtaW5kIGhvdyB0aGUgZGF0YSB3ZXJlIGNvbGxlY3RlZDogc2V2ZXJhbCBtZWFzdXJlbWVudHMgb2YgZ2FpbiB3ZXJlIHRha2VuIGZvciBwb2x5ZW55dGh5bGVuZSBibG9ja3Mgb2Yga25vd24gZGVuc2l0eS4KYGBge3IgZmlnLmFzcD0yLCBmaWcud2lkdGg9NX0KIyBQcmVkaWN0aW9ucwpQcmVkaWN0TG9nR2FpbiA8LSBmdW5jdGlvbihkZW5zaXR5KQogIHByZWRpY3QobGVhc3Quc3F1YXJlcywgZGF0YS5mcmFtZShkZW5zaXR5PWRlbnNpdHkpKSAgIyBQcmVkaWN0IGxvZyhnYWluKSB1c2luZyBkZW5zaXR5CgpQcmVkaWN0RGVuc2l0eUxlYXN0U3F1YXJlcyA8LSBmdW5jdGlvbihnYWluKSB7CiAgaW50ZXJjZXB0IDwtIGNvZWYobGVhc3Quc3F1YXJlcylbWzFdXQogIHNsb3BlIDwtIGNvZWYobGVhc3Quc3F1YXJlcylbWzJdXQogIChsb2coZ2FpbikgLSBpbnRlcmNlcHQpIC8gc2xvcGUgICMgUHJlZGljdCBkZW5zaXR5IHVzaW5nIGdhaW4KfQoKUHJlZGljdERlbnNpdHlMYWQgPC0gZnVuY3Rpb24oZ2FpbikgewogIGludGVyY2VwdCA8LSBjb2VmKGxhZClbWzFdXQogIHNsb3BlIDwtIGNvZWYobGFkKVtbMl1dCiAgKGxvZyhnYWluKSAtIGludGVyY2VwdCkgLyBzbG9wZSAgIyBQcmVkaWN0IGRlbnNpdHkgdXNpbmcgZ2Fpbgp9CgpQcmVkaWN0RGVuc2l0eVF1YW50IDwtIGZ1bmN0aW9uKGdhaW4pIHsKICBpbnRlcmNlcHQgPC0gY29lZihxdWFudClbWzFdXQogIHNsb3BlIDwtIGNvZWYocXVhbnQpW1syXV0KICAobG9nKGdhaW4pIC0gaW50ZXJjZXB0KSAvIHNsb3BlICAjIFByZWRpY3QgZGVuc2l0eSB1c2luZyBnYWluCn0KCgojIDk1JSBwcmVkaWN0aW9uIGFuZCBjb25maWRlbmNlIGludGVydmFscyBvZiBsb2coZ2FpbikgdXNpbmcgZGVuc2l0eQp0IDwtIHF0KC45NzUsIGRmPW0tMikKbWVhbi5kZW5zaXR5IDwtIG1lYW4oZGYubG9nLmF2ZyRkZW5zaXR5KQpzdW1tYXRpb24gPC0gc3VtKChkZi5sb2cuYXZnJGRlbnNpdHkgLSBtZWFuLmRlbnNpdHkpIF4gMikKCnMyIDwtIGFnZ3JlZ2F0ZShsaXN0KHZhcmlhbmNlPWxlYXN0LnNxdWFyZXMucmVzaWR1YWxzJGdhaW4pLCBieT1saXN0KGRlbnNpdHk9bGVhc3Quc3F1YXJlcy5yZXNpZHVhbHMkZGVuc2l0eSksIEZVTj12YXIpCnMucG9vbGVkIDwtIHNxcnQobWVhbihzMiR2YXJpYW5jZSkpCgpjZW50ZXIuZXhwciA8LSBxdW90ZShjZW50ZXIgPC0gUHJlZGljdExvZ0dhaW4oZGVuc2l0eSkpCmNpLndpZHRoLmV4cHIgPC0gcXVvdGUod2lkdGggPC0gdCAqIHMucG9vbGVkICogc3FydCgxL20gKyAoZGVuc2l0eS1tZWFuLmRlbnNpdHkpXjIgLyBzdW1tYXRpb24pKQpwaS53aWR0aC5leHByIDwtIHF1b3RlKHdpZHRoIDwtIHQgKiBzLnBvb2xlZCAqIHNxcnQoMSArIDEvbSArIChkZW5zaXR5LW1lYW4uZGVuc2l0eSleMiAvIHN1bW1hdGlvbikpCgpMb2dHYWluQ2lMb3dlciA8LSBmdW5jdGlvbihkZW5zaXR5KSB7CiAgZXZhbChjZW50ZXIuZXhwcikKICBldmFsKGNpLndpZHRoLmV4cHIpCiAgY2VudGVyIC0gd2lkdGgKfQoKTG9nR2FpbkNpVXBwZXIgPC0gZnVuY3Rpb24oZGVuc2l0eSkgewogIGV2YWwoY2VudGVyLmV4cHIpCiAgZXZhbChjaS53aWR0aC5leHByKQogIGNlbnRlciArIHdpZHRoCn0KCkxvZ0dhaW5QaUxvd2VyIDwtIGZ1bmN0aW9uKGRlbnNpdHkpIHsKICBldmFsKGNlbnRlci5leHByKQogIGV2YWwocGkud2lkdGguZXhwcikKICBjZW50ZXIgLSB3aWR0aAp9CgpMb2dHYWluUGlVcHBlciA8LSBmdW5jdGlvbihkZW5zaXR5KSB7CiAgZXZhbChjZW50ZXIuZXhwcikKICBldmFsKHBpLndpZHRoLmV4cHIpCiAgY2VudGVyICsgd2lkdGgKfQoKCiMgQWRkIGJhbmRzIGFyb3VuZCBsZWFzdCBzcXVhcmVzIGxpbmUKcGxvdChkZi5sb2csIG1haW49dGl0bGUsIHhsYWI9eC5heGlzLCB5bGFiPXkubG9nLmF4aXMsIHhsaW09eC5yYW5nZSwgeWxpbT15LnJhbmdlKQphYmxpbmUobGVhc3Quc3F1YXJlcywgY29sPSdyZWQnKQoKY2kuY29sIDwtICdwdXJwbGUnCnBpLmNvbCA8LSAnYmx1ZScKc3ltYm9sIDwtICctJwpzaXplIDwtIDEuNQpsaW5lLnR5cGUgPC0gMwpsaW5lLndpZHRoIDwtIDAuNwoKY29uZmlkZW5jZS5pbnRlcnZhbHMgPC0gZGF0YS5mcmFtZShkZW5zaXR5PWRmLmxvZy5hdmckZGVuc2l0eSwgbG93ZXI9TG9nR2FpbkNpTG93ZXIoZGYubG9nLmF2ZyRkZW5zaXR5KSwgdXBwZXI9TG9nR2FpbkNpVXBwZXIoZGYubG9nLmF2ZyRkZW5zaXR5KSkKcG9pbnRzKHg9Y29uZmlkZW5jZS5pbnRlcnZhbHMkZGVuc2l0eSwgeT1jb25maWRlbmNlLmludGVydmFscyRsb3dlciwgY29sPWNpLmNvbCwgcGNoPXN5bWJvbCwgY2V4PXNpemUpCnBvaW50cyh4PWNvbmZpZGVuY2UuaW50ZXJ2YWxzJGRlbnNpdHksIHk9Y29uZmlkZW5jZS5pbnRlcnZhbHMkdXBwZXIsIGNvbD1jaS5jb2wsIHBjaD1zeW1ib2wsIGNleD1zaXplKQpsaW5lcyh4PWNvbmZpZGVuY2UuaW50ZXJ2YWxzJGRlbnNpdHksIHk9Y29uZmlkZW5jZS5pbnRlcnZhbHMkbG93ZXIsIGNvbD1jaS5jb2wsIGx0eT1saW5lLnR5cGUsIGx3ZD1saW5lLndpZHRoKQpsaW5lcyh4PWNvbmZpZGVuY2UuaW50ZXJ2YWxzJGRlbnNpdHksIHk9Y29uZmlkZW5jZS5pbnRlcnZhbHMkdXBwZXIsIGNvbD1jaS5jb2wsIGx0eT1saW5lLnR5cGUsIGx3ZD1saW5lLndpZHRoKQoKcHJlZGljdGlvbi5pbnRlcnZhbHMgPC0gZGF0YS5mcmFtZShkZW5zaXR5PWRmLmxvZy5hdmckZGVuc2l0eSwgbG93ZXI9TG9nR2FpblBpTG93ZXIoZGYubG9nLmF2ZyRkZW5zaXR5KSwgdXBwZXI9TG9nR2FpblBpVXBwZXIoZGYubG9nLmF2ZyRkZW5zaXR5KSkKcG9pbnRzKHg9cHJlZGljdGlvbi5pbnRlcnZhbHMkZGVuc2l0eSwgeT1wcmVkaWN0aW9uLmludGVydmFscyRsb3dlciwgY29sPXBpLmNvbCwgcGNoPXN5bWJvbCwgY2V4PXNpemUpCnBvaW50cyh4PXByZWRpY3Rpb24uaW50ZXJ2YWxzJGRlbnNpdHksIHk9cHJlZGljdGlvbi5pbnRlcnZhbHMkdXBwZXIsIGNvbD1waS5jb2wsIHBjaD1zeW1ib2wsIGNleD1zaXplKQpsaW5lcyh4PXByZWRpY3Rpb24uaW50ZXJ2YWxzJGRlbnNpdHksIHk9cHJlZGljdGlvbi5pbnRlcnZhbHMkbG93ZXIsIGNvbD1waS5jb2wsIGx0eT1saW5lLnR5cGUsIGx3ZD1saW5lLndpZHRoKQpsaW5lcyh4PXByZWRpY3Rpb24uaW50ZXJ2YWxzJGRlbnNpdHksIHk9cHJlZGljdGlvbi5pbnRlcnZhbHMkdXBwZXIsIGNvbD1waS5jb2wsIGx0eT1saW5lLnR5cGUsIGx3ZD1saW5lLndpZHRoKQoKbGVnZW5kKCd0b3ByaWdodCcsIGxlZ2VuZD1jKCdMZWFzdCBTcXVhcmVzIFJlZ3Jlc3Npb24gTGluZScsICc5NSUgQ29uZmlkZW5jZSBJbnRlcnZhbCBCYW5kcycsICc5NSUgUHJlZGljdGlvbiBJbnRlcnZhbCBCYW5kcycpLCBjb2w9YygncmVkJywgY2kuY29sLCBwaS5jb2wpLCBsdHk9MSkKCgojIDk1JSBwcmVkaWN0aW9uIGFuZCBjb25maWRlbmNlIGludGVydmFscyBvZiBkZW5zaXR5IHVzaW5nIGdhaW4KaW50ZXJ2YWwgPC0gYygtMSwgMykgICMgSW50ZXJ2YWwgdG8gc2VhcmNoIHRoZSByb290IGluCgpEZW5zaXR5Q2kgPC0gZnVuY3Rpb24oZ2FpbikgewogIGxvd2VyIDwtIHVuaXJvb3QoZnVuY3Rpb24oZGVuc2l0eSkgbG9nKGdhaW4pIC0gTG9nR2FpbkNpTG93ZXIoZGVuc2l0eSksIGludGVydmFsPWludGVydmFsKVtbMV1dCiAgdXBwZXIgPC0gdW5pcm9vdChmdW5jdGlvbihkZW5zaXR5KSBsb2coZ2FpbikgLSBMb2dHYWluQ2lVcHBlcihkZW5zaXR5KSwgaW50ZXJ2YWw9aW50ZXJ2YWwpW1sxXV0KICBjKGxvd2VyLCB1cHBlcikKfQoKRGVuc2l0eVBpIDwtIGZ1bmN0aW9uKGdhaW4pIHsKICBsb3dlciA8LSB1bmlyb290KGZ1bmN0aW9uKGRlbnNpdHkpIGxvZyhnYWluKSAtIExvZ0dhaW5QaUxvd2VyKGRlbnNpdHkpLCBpbnRlcnZhbD1pbnRlcnZhbClbWzFdXQogIHVwcGVyIDwtIHVuaXJvb3QoZnVuY3Rpb24oZGVuc2l0eSkgbG9nKGdhaW4pIC0gTG9nR2FpblBpVXBwZXIoZGVuc2l0eSksIGludGVydmFsPWludGVydmFsKVtbMV1dCiAgYyhsb3dlciwgdXBwZXIpCn0KCgojIFBvaW50IGFuZCBpbnRlcnZhbCBlc3RpbWF0ZXMgZm9yIGV4YW1wbGUgZ2FpbiByZWFkaW5ncwpQcmVkaWN0RGVuc2l0eUxlYXN0U3F1YXJlcygzOC42KSAgIyAzOC42IGlzIHRoZSBhdmVyYWdlIGdhaW4gZm9yIDAuNTA4IGRlbnNpdHkKUHJlZGljdERlbnNpdHlMYWQoMzguNikKUHJlZGljdERlbnNpdHlRdWFudCgzOC42KQpEZW5zaXR5Q2koMzguNikKRGVuc2l0eVBpKDM4LjYpCgpQcmVkaWN0RGVuc2l0eUxlYXN0U3F1YXJlcyg0MjYuNykgICMgNDI2LjcgaXMgdGhlIGF2ZXJhZ2UgZ2FpbiBmb3IgMC4wMDEgZGVuc2l0eQpQcmVkaWN0RGVuc2l0eUxhZCg0MjYuNykKUHJlZGljdERlbnNpdHlRdWFudCg0MjYuNykKRGVuc2l0eUNpKDQyNi43KQpEZW5zaXR5UGkoNDI2LjcpCmBgYAoKCiMjIFNjZW5hcmlvIDM6IENyb3NzLVZhbGlkYXRpb24KVG8gY2hlY2sgaG93IHdlbGwgeW91ciBwcm9jZWR1cmUgd29ya3MsIG9taXQgdGhlIHNldCBvZiBtZWFzdXJlbWVudHMgY29ycmVzcG9uZGluZyB0byB0aGUgYmxvY2sgb2YgZGVuc2l0eSAwLjUwOCwgYXBwbHkgeW91ciAiZXN0aW1hdGlvbiIvY2FsaWJyYXRpb24gcHJvY2VkdXJlIHRvIHRoZSByZW1haW5pbmcgZGF0YSwgYW5kIHByb3ZpZGUgYW4gaW50ZXJ2YWwgZXN0aW1hdGUgZm9yIHRoZSBkZW5zaXR5IG9mIGEgYmxvY2sgd2l0aCBhbiBhdmVyYWdlIHJlYWRpbmcgb2YgMzguNi4gV2hlcmUgZG9lcyB0aGUgYWN0dWFsIGRlbnNpdHkgZmFsbCBpbiB0aGUgaW50ZXJ2YWw/IFRyeSB0aGUgc2FtZSB0ZXN0LCBmb3IgdGhlIHNldCBvZiBtZWFzdXJlbWVudHMgYXQgdGhlIDAuMDAxIGRlbnNpdHkuCmBgYHtyIGZpZy5hc3A9MiwgZmlnLndpZHRoPTV9CmZvciAob21pdHRlZCBpbiBjKDAuNTA4LCAwLjAwMSkpIHsKICAjIE9taXQgbWVhc3VyZW1lbnRzIGNvcnJlc3BvbmRpbmcgdG8gdGhlIHNwZWNpZmllZCBkZW5zaXR5CiAgZGYubG9nLm9taXR0ZWQgPSBkZi5sb2dbd2hpY2goZGYubG9nWydkZW5zaXR5J10gIT0gb21pdHRlZCksIF0KICBkZi5sb2cuYXZnLm9taXR0ZWQgPC0gZGYubG9nLmF2Z1t3aGljaChkZi5sb2cuYXZnWydkZW5zaXR5J10gIT0gb21pdHRlZCksIF0KICAKICAKICAjIFJlZG8gY2FsY3VsYXRpb25zIHVzaW5nIG1vZGlmaWVkIGRhdGFzZXQKICBsZWFzdC5zcXVhcmVzIDwtIGxtKGdhaW5+ZGVuc2l0eSwgZGF0YT1kZi5sb2cuYXZnLm9taXR0ZWQpCiAgCiAgbWVhbi5kZW5zaXR5IDwtIG1lYW4oZGYubG9nLmF2Zy5vbWl0dGVkJGRlbnNpdHkpCiAgc3VtbWF0aW9uIDwtIHN1bSgoZGYubG9nLmF2Zy5vbWl0dGVkJGRlbnNpdHkgLSBtZWFuLmRlbnNpdHkpIF4gMikKICAKICBzMiA8LSBhZ2dyZWdhdGUobGlzdCh2YXJpYW5jZT1sZWFzdC5zcXVhcmVzLnJlc2lkdWFscyRnYWluKSwgYnk9bGlzdChkZW5zaXR5PWxlYXN0LnNxdWFyZXMucmVzaWR1YWxzJGRlbnNpdHkpLCBGVU49dmFyKQogIHMucG9vbGVkIDwtIHNxcnQobWVhbihzMiR2YXJpYW5jZSkpCiAgCiAgY2kud2lkdGguZXhwciA8LSBxdW90ZSh3aWR0aCA8LSB0ICogcy5wb29sZWQgKiBzcXJ0KDEvKG0tMSkgKyAoZGVuc2l0eS1tZWFuLmRlbnNpdHkpXjIgLyBzdW1tYXRpb24pKQogIHBpLndpZHRoLmV4cHIgPC0gcXVvdGUod2lkdGggPC0gdCAqIHMucG9vbGVkICogc3FydCgxICsgMS8obS0xKSArIChkZW5zaXR5LW1lYW4uZGVuc2l0eSleMiAvIHN1bW1hdGlvbikpCiAgCiAgcGxvdChkZi5sb2cub21pdHRlZCwgbWFpbj10aXRsZSwgeGxhYj14LmF4aXMsIHlsYWI9eS5sb2cuYXhpcywgeGxpbT14LnJhbmdlLCB5bGltPXkucmFuZ2UpCiAgYWJsaW5lKGxlYXN0LnNxdWFyZXMsIGNvbD0ncmVkJykKICAKICBjaS5jb2wgPC0gJ3B1cnBsZScKICBwaS5jb2wgPC0gJ2JsdWUnCiAgc3ltYm9sIDwtICctJwogIHNpemUgPC0gMS41CiAgbGluZS50eXBlIDwtIDMKICBsaW5lLndpZHRoIDwtIDAuNwogIAogIGNvbmZpZGVuY2UuaW50ZXJ2YWxzIDwtIGRhdGEuZnJhbWUoZGVuc2l0eT1kZi5sb2cuYXZnLm9taXR0ZWQkZGVuc2l0eSwgbG93ZXI9TG9nR2FpbkNpTG93ZXIoZGYubG9nLmF2Zy5vbWl0dGVkJGRlbnNpdHkpLCB1cHBlcj1Mb2dHYWluQ2lVcHBlcihkZi5sb2cuYXZnLm9taXR0ZWQkZGVuc2l0eSkpCiAgcG9pbnRzKHg9Y29uZmlkZW5jZS5pbnRlcnZhbHMkZGVuc2l0eSwgeT1jb25maWRlbmNlLmludGVydmFscyRsb3dlciwgY29sPWNpLmNvbCwgcGNoPXN5bWJvbCwgY2V4PXNpemUpCiAgcG9pbnRzKHg9Y29uZmlkZW5jZS5pbnRlcnZhbHMkZGVuc2l0eSwgeT1jb25maWRlbmNlLmludGVydmFscyR1cHBlciwgY29sPWNpLmNvbCwgcGNoPXN5bWJvbCwgY2V4PXNpemUpCiAgbGluZXMoeD1jb25maWRlbmNlLmludGVydmFscyRkZW5zaXR5LCB5PWNvbmZpZGVuY2UuaW50ZXJ2YWxzJGxvd2VyLCBjb2w9Y2kuY29sLCBsdHk9bGluZS50eXBlLCBsd2Q9bGluZS53aWR0aCkKICBsaW5lcyh4PWNvbmZpZGVuY2UuaW50ZXJ2YWxzJGRlbnNpdHksIHk9Y29uZmlkZW5jZS5pbnRlcnZhbHMkdXBwZXIsIGNvbD1jaS5jb2wsIGx0eT1saW5lLnR5cGUsIGx3ZD1saW5lLndpZHRoKQogIAogIHByZWRpY3Rpb24uaW50ZXJ2YWxzIDwtIGRhdGEuZnJhbWUoZGVuc2l0eT1kZi5sb2cuYXZnLm9taXR0ZWQkZGVuc2l0eSwgbG93ZXI9TG9nR2FpblBpTG93ZXIoZGYubG9nLmF2Zy5vbWl0dGVkJGRlbnNpdHkpLCB1cHBlcj1Mb2dHYWluUGlVcHBlcihkZi5sb2cuYXZnLm9taXR0ZWQkZGVuc2l0eSkpCiAgcG9pbnRzKHg9cHJlZGljdGlvbi5pbnRlcnZhbHMkZGVuc2l0eSwgeT1wcmVkaWN0aW9uLmludGVydmFscyRsb3dlciwgY29sPXBpLmNvbCwgcGNoPXN5bWJvbCwgY2V4PXNpemUpCiAgcG9pbnRzKHg9cHJlZGljdGlvbi5pbnRlcnZhbHMkZGVuc2l0eSwgeT1wcmVkaWN0aW9uLmludGVydmFscyR1cHBlciwgY29sPXBpLmNvbCwgcGNoPXN5bWJvbCwgY2V4PXNpemUpCiAgbGluZXMoeD1wcmVkaWN0aW9uLmludGVydmFscyRkZW5zaXR5LCB5PXByZWRpY3Rpb24uaW50ZXJ2YWxzJGxvd2VyLCBjb2w9cGkuY29sLCBsdHk9bGluZS50eXBlLCBsd2Q9bGluZS53aWR0aCkKICBsaW5lcyh4PXByZWRpY3Rpb24uaW50ZXJ2YWxzJGRlbnNpdHksIHk9cHJlZGljdGlvbi5pbnRlcnZhbHMkdXBwZXIsIGNvbD1waS5jb2wsIGx0eT1saW5lLnR5cGUsIGx3ZD1saW5lLndpZHRoKQogIAogIGxlZ2VuZCgndG9wcmlnaHQnLCBsZWdlbmQ9YygnTGVhc3QgU3F1YXJlcyBSZWdyZXNzaW9uIExpbmUnLCAnOTUlIENvbmZpZGVuY2UgSW50ZXJ2YWwgQmFuZHMnLCAnOTUlIFByZWRpY3Rpb24gSW50ZXJ2YWwgQmFuZHMnKSwgY29sPWMoJ3JlZCcsIGNpLmNvbCwgcGkuY29sKSwgbHR5PTEpCiAgCiAgcHJpbnQoUHJlZGljdERlbnNpdHlMZWFzdFNxdWFyZXMoMzguNikpICAjIDM4LjYgaXMgdGhlIGF2ZXJhZ2UgZ2FpbiBmb3IgMC41MDggZGVuc2l0eQogIHByaW50KERlbnNpdHlDaSgzOC42KSkKICBwcmludChEZW5zaXR5UGkoMzguNikpCiAgCiAgcHJpbnQoUHJlZGljdERlbnNpdHlMZWFzdFNxdWFyZXMoNDI2LjcpKSAgIyA0MjYuNyBpcyB0aGUgYXZlcmFnZSBnYWluIGZvciAwLjAwMSBkZW5zaXR5CiAgcHJpbnQoRGVuc2l0eUNpKDQyNi43KSkKICBwcmludChEZW5zaXR5UGkoNDI2LjcpKQp9CmBgYAoKCiMjIEFkZGl0aW9uYWwgU2NlbmFyaW86IFRlbXBlcmF0dXJlLCBET1ksIGFuZCBMYXRpdHVkZS4KVXNlIHRoZSBhZGRpdGlvbmFsIGRhdGFzZXQgdG8gY29uc3RydWN0IGEgbW9kZWwgZml0dGluZyB0ZW1wZXJhdHVyZSB3aXRoIERPWSwgbGF0aXR1ZGUsIGFuZCBvdGhlciByZWFzb25hYmxlIGZlYXR1cmVzLiBUcnkgc2tldGNoaW5nIHRoZSBsZWFzdCBzcXVhcmVzIGxpbmUgb24gYSBzY2F0dGVyIHBsb3QuIFdlIGFpbSB0byBpbnZlc3RpZ2F0ZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGVtcGVyYXR1cmUgYW5kIHRoZSBET1ksIGFuZCBpdHMgbGF0aXR1ZGUuCmBgYHtyfQojIENoZWNrIHRoZSBjb3JyZWxhdGlvbgpkYXRhIDwtIHJlYWQuY3N2KCdGdWxsIFJlc29sdXRpb24gRGF0YS82NDUwNjQyMC5jc3YnLCBoZWFkZXI9VFJVRSkKZGF0YSA8LSBkYXRhWyxjKCdIb3VyJywnRE9ZJywnUE9TX0RPWScsJ0xhdCcsJ0xvbicsJ1RzJywnQlAnKV0KCiMgRHJvcCB0aGUgZXh0cmVtZSBvdXRsaWVyIGNhc2UKI2RhdGEgPC0gZGF0YVt3aGljaChkYXRhJFRzPi0yMDApLF0KZGF0YV9tYXRyaXggPC0gYXMubWF0cml4KGRhdGEpCgojIENvcnJlbGF0aW9uIE1hdHJpeApjb3JyX21hdHJpeCA8LSBjb3IoZGF0YV9tYXRyaXgpCmNvcnJfbWF0cml4CmBgYAoKYGBge3J9CiMgbGVhc3Qgc3F1YXJlcyBsaW5lCmZpdDwtbG0oZm9ybXVsYSA9IFRzIH4gRE9ZICsgTGF0LCBkYXRhID0gZGF0YSkKc3VtbWFyeShmaXQpCgpnZ3Bsb3QoZGF0YSxhZXMoeD1ET1ksIHk9VHMpKSArIAogIGdlb21fcG9pbnQoY29sb3I9JyMyOTgwQjknLCBzaXplID0gNCkgKyAKICBnZW9tX3Ntb290aChtZXRob2Q9bG0sIGNvbG9yPScjMkMzRTUwJykKCmdncGxvdChkYXRhLGFlcyh4PUxhdCwgeT1UcykpICsgCiAgZ2VvbV9wb2ludChjb2xvcj0nIzI5ODBCOScsIHNpemUgPSA0KSArIAogIGdlb21fc21vb3RoKG1ldGhvZD1sbSwgY29sb3I9JyMyQzNFNTAnKQoKdGl0bGUucmVzaWR1YWxzMSA8LSAnUmVzaWR1YWxzIG9mIExlYXN0IFNxdWFyZXMgUmVncmVzc2lvbiBMaW5lJwpwbG90KGZpdCRyZXNpZHVhbHMsIG1haW49dGl0bGUucmVzaWR1YWxzMSkKYWJsaW5lKDAsIDAsIGNvbD0ncmVkJykKCm51bS5iaW5zIDwtIDEwCmhpc3QoZml0JHJlc2lkdWFscywgYnJlYWtzPW51bS5iaW5zLCBtYWluPXRpdGxlLnJlc2lkdWFsczEsIHhsYWI9J1RlbXBlcmF0dXJlJywgY29sPSdyZWQnKQoKcXFub3JtKGZpdCRyZXNpZHVhbHMsIG1haW49cGFzdGUoJ05vcm1hbCBRLVEgUGxvdCB3aXRoJywgdGl0bGUucmVzaWR1YWxzMSksIGNleC5tYWluPTEpCnFxbGluZShmaXQkcmVzaWR1YWxzLCBjb2w9J3JlZCcpCmBgYAoKYGBge3J9CiMgQXR0ZW1wdCBmb3IgTXVsdGlwbGUgUmVncmVzc2lvbnMKZGF0YSRNaWRuaWdodHMgPC0gMApkYXRhJE1pZG5pZ2h0c1t3aGljaChkYXRhJEhvdXI8NildIDwtIDEKZGF0YSRNb3JuaW5ncyA8LSAwCmRhdGEkTW9ybmluZ3Nbd2hpY2goZGF0YSRIb3VyPj02ICYgZGF0YSRIb3VyPDExKV0gPC0gMSAKZGF0YSROb29uIDwtIDAKZGF0YSROb29uW3doaWNoKGRhdGEkSG91cj49MTEgJiBkYXRhJEhvdXI8MTUpXSA8LSAxCmRhdGEkQWZ0ZXJub29uIDwtIDAKZGF0YSRBZnRlcm5vb25bd2hpY2goZGF0YSRIb3VyPj0xNSAmIGRhdGEkSG91cjwyMCldIDwtIDEKZGF0YSROaWdodHMgPC0gMApkYXRhJE5pZ2h0c1t3aGljaChkYXRhJEhvdXI+PTIwKV0gPC0gMQpgYGA=
=======
<<<<<<< HEAD
LS0tCnRpdGxlOiAnQ0FTRSBTVFVEWSA0OicKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKVGhpcyBzdHVkeSBhbGxvd3MgdXMgdG8gcmV2aXNpdC9yZW5ldwoKMS4gUmVncmVzc2lvbiBtb2RlbGluZwoyLiBQcm9wZXJ0aWVzIG9mIExlYXN0IFNxdWFyZXMvRml0dGluZyAiYSBsaW5lIgozLiBNdWx0aXBsZSBvYnNlcnZhdGlvbgoKRGF0YXNldHMgZm9yIHRoaXMgc3R1ZHkgYXJlCgoxLiBUaGUgbWFpbiBmaWxlOiBnYXVnZS50eHQKMi4gU3VwcGxlbWVudGFyeSBsYXJnZS1zY2FsZSBmaWxlczogZG93bmxvYWQgdGhlIGZvbGxvd2luZyBmb2xkZXIgRnVsbCBSZXNvbHV0aW9uIERhdGEuemlwIE1vcmUgaW5mb3JtYXRpb24gYWJvdXQgdGhlIHN1cHBsZW1lbnRhcnkgZmlsZSBjYW4gYmUgZm91bmQgYXQgaHR0cDovL2lhYnAuYXBsLndhc2hpbmd0b24uZWR1L2RhdGEuaHRtbCBhcyB3ZWxsIGFzIGh0dHA6Ly9uc2lkYy5vcmcvZGF0YS9HMDA3OTEKCgojIyBRdWVzdGlvbgpUaGUgYWltIG9mIHRoaXMgbGFiIGlzIHRvIHByb3ZpZGUgYSBzaW1wbGUgcHJvY2VkdXJlIGZvciBjb252ZXJ0aW5nIGdhaW4gaW50byBkZW5zaXR5IHdoZW4gdGhlIGdhdWdlIGlzIGluIG9wZXJhdGlvbi4gS2VlcCBpbiBtaW5kIHRoYXQgdGhlIGV4cGVyaW1lbnQgd2FzIGNvbmR1Y3RlZCBieSB2YXJ5aW5nIGRlbnNpdHkgYW5kIG1lYXN1cmluZyB0aGUgcmVzcG9uc2UgaW4gZ2FpbiwgYnV0IHdoZW4gdGhlIGdhdWdlIGlzIHVsdGltYXRlbHkgaW4gdXNlLCB0aGUgc25vdy1wYWNrIGRlbnNpdHkgaXMgdG8gYmUgZXN0aW1hdGVkIGZyb20gdGhlIG1lYXN1cmVkIGdhaW4uCgoKIyMgU2V0dXAKYGBge3J9CmRmIDwtIHJlYWQudGFibGUoJ2dhdWdlLTF3YjF3YTYtMmdwZWw0MS50eHQnLCBoZWFkZXI9VFJVRSkKCiNpbnN0YWxsLnBhY2thZ2VzKCdMMXBhY2snKQpsaWJyYXJ5KEwxcGFjaykgICMgVXNlZCBmb3IgbGVhc3QgYWJzb2x1dGUgZGV2aWF0aW9ucyByZWdyZXNzaW9uIGxpbmUKYGBgCgoKIyMgU2NlbmFyaW8gMTogRml0dGluZwpVc2UgdGhlIGRhdGEgdG8gZml0IHRoZSBnYWluLCBvciBhIHRyYW5zZm9ybWF0aW9uIG9mIGdhaW4sIHRvIGRlbnNpdHkuIFRyeSBza2V0Y2hpbmcgdGhlIGxlYXN0IHNxdWFyZXMgbGluZSBvbiBhIHNjYXR0ZXIgcGxvdC4KCiogRG8gdGhlIHJlc2lkdWFscyBpbmRpY2F0ZSBhbnkgcHJvYmxlbXMgd2l0aCB0aGUgZml0PwoqIElmIHRoZSBkZW5zaXRpZXMgb2YgdGhlIHBvbHlldGh5bGVuZSBibG9ja3MgYXJlIG5vdCByZXBvcnRlZCBleGFjdGx5LCBob3cgbWlnaHQgdGhpcyBhZmZlY3QgdGhlIGZpdD8KKiBXaGF0IGlmIHRoZSBibG9ja3Mgb2YgcG9seWV0aHlsZW5lIHdlcmUgbm90IG1lYXN1cmVkIGluIHJhbmRvbSBvcmRlcj8KYGBge3J9CiMgUGxvdCByYXcgZGF0YQp0aXRsZSA8LSAnRGVuc2l0eSB2cy4gR2FpbicKeC5heGlzIDwtIGV4cHJlc3Npb24oJ0RlbnNpdHkgKGcvY20nXjMqJyknKSAKeS5heGlzIDwtICdHYWluJwpwbG90KGRmLCBtYWluPXRpdGxlLCB4bGFiPXguYXhpcywgeWxhYj15LmF4aXMpCgoKIyBUYWtlIGxvZyB0cmFuc2Zvcm1hdGlvbiBvZiByZXNwb25zZSB2YXJpYWJsZSAoZ2FpbikKeS5sb2cuYXhpcyA9ICdsb2coR2FpbiknCmRmLmxvZyA9IGRhdGEuZnJhbWUoZGZbJ2RlbnNpdHknXSwgbG9nKGRmWydnYWluJ10pKQpwbG90KGRmLmxvZywgbWFpbj10aXRsZSwgeGxhYj14LmF4aXMsIHlsYWI9eS5sb2cuYXhpcykKCgojIEF2ZXJhZ2UgcmVwbGljYXRlIG1lYXN1cmVtZW50cwpkZi5sb2cuYXZnID0gYWdncmVnYXRlKGxpc3QoZ2Fpbj1kZi5sb2ckZ2FpbiksIGJ5PWxpc3QoZGVuc2l0eT1kZi5sb2ckZGVuc2l0eSksIEZVTj1tZWFuKQpwbG90KGRmLmxvZy5hdmcsIG1haW49dGl0bGUsIHhsYWI9eC5heGlzLCB5bGFiPXkubG9nLmF4aXMpCgoKIyBGaXQgZ2FpbiB0byBkZW5zaXR5CmNvcihkZi5sb2cuYXZnKQoKbGVhc3Quc3F1YXJlcyA8LSBsbShnYWlufmRlbnNpdHksIGRhdGE9ZGYubG9nLmF2ZykKbGVhc3QuYWJzb2x1dGUuZGV2aWF0aW9ucyA8LSBsYWQoZ2Fpbn5kZW5zaXR5LCBkYXRhPWRmLmxvZy5hdmcpCgpwbG90KGRmLmxvZy5hdmcsIG1haW49dGl0bGUsIHhsYWI9eC5heGlzLCB5bGFiPXkubG9nLmF4aXMpCmFibGluZShsZWFzdC5zcXVhcmVzLCBjb2w9J3JlZCcpCmFibGluZShsZWFzdC5hYnNvbHV0ZS5kZXZpYXRpb25zLCBjb2w9J2JsdWUnKQpsZWdlbmQoJ3RvcHJpZ2h0JywgbGVnZW5kPWMoJ0xlYXN0IFNxdWFyZXMnLCAnTGVhc3QgQWJzb2x1dGUgRGV2aWF0aW9ucycpLCBjb2w9YygncmVkJywgJ2JsdWUnKSwgbHR5PTEpOwoKbGVhc3Quc3F1YXJlcwpzdW1tYXJ5KGxlYXN0LnNxdWFyZXMpCmxlYXN0LmFic29sdXRlLmRldmlhdGlvbnMKc3VtbWFyeShsZWFzdC5hYnNvbHV0ZS5kZXZpYXRpb25zKQoKCiMgQ2hlY2sgY29uZGl0aW9ucyBmb3IgbGluZWFyIHJlZ3Jlc3Npb246IGxpbmVhcml0eSwgbm9ybWFsaXR5IG9mIHJlc2lkdWFscywgY29uc3RhbnQgdmFyaWFiaWxpdHkKdGl0bGUucmVzaWR1YWxzMSA8LSAnUmVzaWR1YWxzIG9mIExlYXN0IFNxdWFyZXMgUmVncmVzc2lvbiBMaW5lJwp0aXRsZS5yZXNpZHVhbHMyIDwtICdSZXNpZHVhbHMgb2YgTGVhc3QgQWJzb2x1dGUgRGV2aWF0aW9ucyBSZWdyZXNzaW9uIExpbmUnCnBsb3QobGVhc3Quc3F1YXJlcyRyZXNpZHVhbHMsIG1haW49dGl0bGUucmVzaWR1YWxzMSwgeWxhYj15LmF4aXMpCmFibGluZSgwLCAwLCBjb2w9J3JlZCcpCnBsb3QobGVhc3QuYWJzb2x1dGUuZGV2aWF0aW9ucyRyZXNpZHVhbHMsIG1haW49dGl0bGUucmVzaWR1YWxzMiwgeWxhYj15LmF4aXMpCmFibGluZSgwLCAwLCBjb2w9J2JsdWUnKQoKbnVtLmJpbnMgPC0gMTAKaGlzdChsZWFzdC5zcXVhcmVzJHJlc2lkdWFscywgYnJlYWtzPW51bS5iaW5zLCBtYWluPXRpdGxlLnJlc2lkdWFsczEsIHhsYWI9eS5heGlzLCBjb2w9J3JlZCcpCmhpc3QobGVhc3QuYWJzb2x1dGUuZGV2aWF0aW9ucyRyZXNpZHVhbHMsIGJyZWFrcz1udW0uYmlucywgbWFpbj10aXRsZS5yZXNpZHVhbHMyLCB4bGFiPXkuYXhpcywgY29sPSdibHVlJykKCnFxbm9ybShsZWFzdC5zcXVhcmVzJHJlc2lkdWFscywgbWFpbj1wYXN0ZSgnTm9ybWFsIFEtUSBQbG90IHdpdGgnLCB0aXRsZS5yZXNpZHVhbHMxKSwgY2V4Lm1haW49MSkKcXFsaW5lKGxlYXN0LnNxdWFyZXMkcmVzaWR1YWxzLCBjb2w9J3JlZCcpCnFxbm9ybShsZWFzdC5hYnNvbHV0ZS5kZXZpYXRpb25zJHJlc2lkdWFscywgbWFpbj1wYXN0ZSgnTm9ybWFsIFEtUSBQbG90IHdpdGgnLCB0aXRsZS5yZXNpZHVhbHMyKSwgY2V4Lm1haW49MSkKcXFsaW5lKGxlYXN0LmFic29sdXRlLmRldmlhdGlvbnMkcmVzaWR1YWxzLCBjb2w9J2JsdWUnKQoKIyBJZiB0aGUgZGVuc2l0aWVzIG9mIHRoZSBwb2x5ZXRoeWxlbmUgYmxvY2tzIHdlcmUgbm90IHJlcG9ydGVkIGV4YWN0bHksIG5vdCBvbmx5IHdvdWxkIHdlIG5vdCBrbm93IHRoZSBkZW5zaXR5IG9mIG91ciBzbm93LCBvdXIgZXhwbGFuYXRvcnkgdmFyaWFibGUsIGJ1dCB3ZSBjb3VsZCBhbHNvIHJldHJpZXZlIGluYWNjdXJhdGUgZGF0YSBmb3IgdGhlIGdhaW4gZnJvbSB0aGUgcGhvdG9ucy4gSXQgaXMgcG9zc2libGUgdGhhdCBpZiB0aGUgZGVuc2l0eSBvZiB0aGUgc25vdyB3YXMgbm90IHByb3Blcmx5IHJlcG9ydGVkLCBvdXIgd2hvbGUgZGF0YSBzZXQgd291bGQgYmUgZmxhd2VkIGFuZCB3ZSBjb3VsZCBhcnJpdmUgYXQgYSBjYWxpYnJhdGlvbiBwcm9jZWR1cmUgZGlmZmVyZW50IGZyb20gd2hhdCB3ZSB3b3VsZCBoYXZlIHdhbnRlZC4KCiMgU2luY2UgdGhlIGJsb2NrcyB0aGVtc2VsdmVzIHdlcmUgaW4gcmFuZG9tIGxvY2F0aW9ucywgdGhlcmVmb3JlIGlmIHRoZSBtZWFzdXJlbWVudCB3ZXJlIG5vdCB0YWtlbiByYW5kb21seSwgdGhlbiBpdCBtaWdodCBoYXBwZW4gdGhhdCB0aGUgbWVhc3VyZW1lbnRzIG1pZ2h0IGJlIHRha2VuIGluIGEgb25seSBzcGVjaWZpYyBhcmVhIGFuZCB0aHVzIGNhdXNpbmcgYmlhcy4KCiMgSWYgdGhlIGJsb2NrcyBvZiBwb2x5ZXRoeWxlbmUgd2VyZSBub3QgbWVhc3VyZWQgaW4gcmFuZG9tIG9yZGVyLCB0aGVyZSBjb3VsZCBiZSBhIGRlcGVuZGVuY2Ugb24gdGhlIG1lYXN1cmVtZW50cyBvZiB0aGUgc25vdyBkZW5zaXRpZXMsIGFuZCBvdXIgZGF0YSB3b3VsZCBub3QgYmUgaS5pLmQuIElmIHdlIGhhbmRwaWNrZWQgd2hpY2ggYmxvY2tzIHRvIG1lYXN1cmUgb3IgcGlja2VkIHRoZW0gaW4gYSBwcmVkZXRlcm1pbmVkIG9yZGVyLCB0aGUgZGVuc2l0eSBvZiB0aGUgc25vdyBibG9ja3MgY291bGQgaW5mbHVlbmNlIGhvdyB0aGUgZ2FpbiB3YXMgcmVjb3JkZWQgZm9yIGVhY2ggYmxvY2sgb2Ygc25vdyBhbmQgYWxzbyBwcm9kdWNlIGluYWNjdXJhdGUgcmVzdWx0cy4KYGBgCgoKIyMgU2NlbmFyaW8gMjogUHJlZGljdGluZwpVbHRpbWF0ZWx5IHdlIGFyZSBpbnRlcmVzdGVkIGluIGFuc3dlcmluZyBxdWVzdGlvbnMgc3VjaCBhczogR2l2ZW4gYSBnYWluIHJlYWRpbmcgb2YgMzguNiwgd2hhdCBpcyB0aGUgZGVuc2l0eSBvZiB0aGUgc25vdy1wYWNrPyBHaXZlbiBhIGdhaW4gcmVhZGluZyBvZiA0MjYuNywgd2hhdCBpcyB0aGUgZGVuc2l0eSBvZiB0aGUgc25vdy1wYWNrPyBUaGVzZSB0d28gbnVtZXJpYyB2YWx1ZXMsIDM4LjYgYW5kIDQyNi43LCB3ZXJlIGNob3NlbiBiZWNhdXNlIHRoZXkgYXJlIHRoZSBhdmVyYWdlIGdhaW5zIGZvciB0aGUgMC41MDggYW5kIDAuMDAxIGRlbnNpdGllcywgcmVzcGVjdGl2ZWx5LgoKKiBEZXZlbG9wIGEgcHJvY2VkdXJlIGZvciBhZGRpbmcgYmFuZHMgYXJvdW5kIHlvdXIgbGVhc3Qgc3F1YXJlcyBsaW5lIHRoYXQgY2FuIGJlIHVzZWQgdG8gbWFrZSBpbnRlcnZhbCBlc3RpbWF0ZXMgZm9yIHRoZSBzbm93LXBhY2sgZGVuc2l0eSBmcm9tIGdhaW4gbWVhc3VyZW1lbnRzLiBLZWVwIGluIG1pbmQgaG93IHRoZSBkYXRhIHdlcmUgY29sbGVjdGVkOiBzZXZlcmFsIG1lYXN1cmVtZW50cyBvZiBnYWluIHdlcmUgdGFrZW4gZm9yIHBvbHllbnl0aHlsZW5lIGJsb2NrcyBvZiBrbm93biBkZW5zaXR5LgoKYGBge3J9CnByZWQuaW50ID0gIHByZWRpY3QobGVhc3Quc3F1YXJlcywgaW50ZXJ2YWw9InByZWRpY3Rpb24iLCBsZXZlbD0uOTUpCnBsb3QocHJlZC5pbnQpCmBgYAoKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKIyBMZWFzdCBTcXVhcmUgYjAgYW5kIGIxIHZhbHVlCmIxIDwtICBhcy5udW1lcmljKGNvZWZmaWNpZW50cygobGVhc3Quc3F1YXJlcykpWzJdKQpiMCA8LSAgYXMubnVtZXJpYyhjb2VmZmljaWVudHMoKGxlYXN0LnNxdWFyZXMpKVsxXSkKCiMgRnVuY3Rpb24gdG8gdXNlIGdhaW4gdG8gcHJlZGljdCBkZW5zaXR5IApscy5yZWdyZXNzaW9uIDwtIGZ1bmN0aW9uKGdhaW4pewogIGxvZy5nYWluIDwtICBsb2coZ2FpbikKICBlc3RpbWF0ZWQuZGVuc2l0eSA8LSAgKGxvZy5nYWluIC0gYjApIC8gYjE7CiAgcmV0dXJuKGVzdGltYXRlZC5kZW5zaXR5KTsKfQoKIyBFc3RpbWF0ZXMgZm9yIGRlbnNpdHkKZGVuc2l0eS4xIDwtIGxzLnJlZ3Jlc3Npb24oMzguNikKZGVuc2l0eS4yIDwtIGxzLnJlZ3Jlc3Npb24oNDI2LjcpCgojIEdyYXBoIGZvciBDb25maWRlbmNlIEludGVydmFsIEJhbmRzIGZvciB0d28gZXN0aW1hdGVzCmdncGxvdChkZi5sb2cuYXZnLGFlcyh4PWRlbnNpdHksIHk9Z2FpbikpICsgCiAgZ2VvbV9wb2ludChjb2xvcj0nIzI5ODBCOScsIHNpemUgPSA0KSArIAogIGdlb21fc21vb3RoKG1ldGhvZD1sbSwgY29sb3I9JyMyQzNFNTAnKStnZW9tX3BvaW50KCkgKwogIGdlb21fcG9pbnQoYWVzKHg9MC41MDgsIHk9My42NTc0NSksIGNvbG91cj0ieWVsbG93IikgCgpnZ3Bsb3QoZGYubG9nLmF2ZyxhZXMoeD1kZW5zaXR5LCB5PWdhaW4pKSArIAogIGdlb21fcG9pbnQoY29sb3I9JyMyOTgwQjknLCBzaXplID0gNCkgKyAKICBnZW9tX3Ntb290aChtZXRob2Q9bG0sIGNvbG9yPScjMkMzRTUwJykrZ2VvbV9wb2ludCgpICsKICBnZW9tX3BvaW50KGFlcyh4PTAuNTA4LCB5PTMuNjU3NDUpLCBjb2xvdXI9InllbGxvdyIpICsKICBnZW9tX3BvaW50KCkrZ2VvbV9wb2ludChhZXMoeD0wLjAwMSwgeT01Ljk5MjY2KSwgY29sb3VyPSJyZWQiKQoKIyBQYXJhbWV0ZXJzCmRlbHRhX2ggPC1zZChsZWFzdC5zcXVhcmVzJHJlc2lkdWFscykKeiA8LSBxbm9ybSgwLjk3NSkKbSA8LSA5CnhfYmFyIDwtIG1lYW4oZGYkZGVuc2l0eSkKZGVuIDwtIHN1bSgoZGYkZGVuc2l0eS14X2JhcikqKjIpCgojIFByZWRpY3Rpb24gSW50ZXJ2YWwgCmxvd2VyLnBpLmJvdW5kIDwtIGZ1bmN0aW9uKGdhaW4pewogIHJldHVybigoLXNxcnQoZGVuKSpzcXJ0KDkqeF9iYXIqeF9iYXIqYjEqYjEvei96L2RlbHRhX2gvZGVsdGFfaCsxOCp4X2JhcipiMS96L2RlbHRhX2gqKGIwLWxvZyhnYWluKSkvei9kZWx0YV9oKzEwKmRlbipiMSpiMS96L2RlbHRhX2gvei9kZWx0YV9oKzkqKGIwLWxvZyhnYWluKSkqKGIwLWxvZyhnYWluKSkvei96L2RlbHRhX2gvZGVsdGFfaC0xMCktMyp4X2Jhci0zKmRlbipiMSooYjAtbG9nKGdhaW4pKS96L3ovZGVsdGFfaC9kZWx0YV9oKS8oMyooZGVuKihiMS96L2RlbHRhX2gpXjIpLTEpKQp9CnVwcGVyLnBpLmJvdW5kIDwtIGZ1bmN0aW9uKGdhaW4pewogIHJldHVybigoc3FydChkZW4pKnNxcnQoOSp4X2Jhcip4X2JhcipiMSpiMS96L3ovZGVsdGFfaC9kZWx0YV9oKzE4KnhfYmFyKmIxL3ovZGVsdGFfaCooYjAtbG9nKGdhaW4pKS96L2RlbHRhX2grMTAqZGVuKmIxKmIxL3ovZGVsdGFfaC96L2RlbHRhX2grOSooYjAtbG9nKGdhaW4pKSooYjAtbG9nKGdhaW4pKS96L3ovZGVsdGFfaC9kZWx0YV9oLTEwKS0zKnhfYmFyLTMqZGVuKmIxKihiMC1sb2coZ2FpbikpL3ovei9kZWx0YV9oL2RlbHRhX2gpLygzKihkZW4qKGIxL3ovZGVsdGFfaCleMiktMSkpCn0KcHJpbnQoIlRoZSBQcmVkaWN0aW9uIEludGVydmFsIGZvciB0aGUgcHJlZGljdGVkIGRlbnNpdHkgZ2l2ZW4gZ2FpbiA9IDM4LjYgaXMiKQpsb3dlci5waS5ib3VuZCgzOC42KQp1cHBlci5waS5ib3VuZCgzOC42KQpwcmludCgiVGhlIFByZWRpY3Rpb24gSW50ZXJ2YWwgZm9yIHRoZSBwcmVkaWN0ZWQgZGVuc2l0eSBnaXZlbiBnYWluID0gNDI2LjcgaXMiKQpsb3dlci5waS5ib3VuZCg0MjYuNykKdXBwZXIucGkuYm91bmQoNDI2LjcpCgojIFBhcmFtZXRlcnMKdCA8LSBxdCgwLjk3NSwgbS0yKQojIENvbmZpZGVuY2UgSW50ZXJ2YWwKbG93ZXIuY2kuYm91bmQgPC0gZnVuY3Rpb24oZ2Fpbil7CiAgcmV0dXJuKCgtc3FydChkZW4pKnNxcnQoOSp4X2Jhcip4X2JhcipiMSpiMS90L3QvZGVsdGFfaC9kZWx0YV9oKzE4KnhfYmFyKmIxL3QvZGVsdGFfaCooYjAtbG9nKGdhaW4pKS90L2RlbHRhX2grOSooYjAtbG9nKGdhaW4pKSooYjAtbG9nKGdhaW4pKS90L3QvZGVsdGFfaC9kZWx0YV9oLTEpLTMqeF9iYXItMypkZW4qYjEqKGIwLWxvZyhnYWluKSkvdC90L2RlbHRhX2gvZGVsdGFfaCkvKDMqKGRlbiooYjEvdC9kZWx0YV9oKV4yKS0xKSkKfQp1cHBlci5jaS5ib3VuZCA8LSBmdW5jdGlvbihnYWluKXsKICByZXR1cm4oKHNxcnQoZGVuKSpzcXJ0KDkqeF9iYXIqeF9iYXIqYjEqYjEvdC90L2RlbHRhX2gvZGVsdGFfaCsxOCp4X2JhcipiMS90L2RlbHRhX2gqKGIwLWxvZyhnYWluKSkvdC9kZWx0YV9oKzkqKGIwLWxvZyhnYWluKSkqKGIwLWxvZyhnYWluKSkvdC90L2RlbHRhX2gvZGVsdGFfaC0xKS0zKnhfYmFyLTMqZGVuKmIxKihiMC1sb2coZ2FpbikpL3QvdC9kZWx0YV9oL2RlbHRhX2gpLygzKihkZW4qKGIxL3QvZGVsdGFfaCleMiktMSkpCn0KcHJpbnQoIlRoZSBDb25maWRlbmNlIEludGVydmFsIGZvciB0aGUgcHJlZGljdGVkIGRlbnNpdHkgZ2l2ZW4gZ2FpbiA9IDM4LjYgaXMiKQpsb3dlci5jaS5ib3VuZCgzOC42KQp1cHBlci5jaS5ib3VuZCgzOC42KQpwcmludCgiVGhlIENvbmZpZGVuY2UgSW50ZXJ2YWwgZm9yIHRoZSBwcmVkaWN0ZWQgZGVuc2l0eSBnaXZlbiBnYWluID0gNDI2LjcgaXMiKQpsb3dlci5jaS5ib3VuZCg0MjYuNykKdXBwZXIuY2kuYm91bmQoNDI2LjcpCgpgYGAKCmBgYHtyfQojIENvbnN0cnVjdCBDb25maWRlbmNlIEludGVydmFsIGZvciBkZW5zaXR5ID0gMC41MDgKbmV3LmRhdGEgPC0gZGF0YS5mcmFtZShkZW5zaXR5ID0gMC41MDgpCmxvZ19wcmVkaWN0aW9uID0gcHJlZGljdChsZWFzdC5zcXVhcmVzLCBuZXcuZGF0YSwgaW50ZXJ2YWw9ImNvbmZpZGVuY2UiKQpsb2dfcHJlZGljdGlvbgpwcmVkaWN0aW9uIDwtIGV4cChsb2dfcHJlZGljdGlvbikKcHJlZGljdGlvbgojIEludGVycHJldGF0aW9uOiBGcm9tIHRoZSBvdXRwdXQsIHRoZSBmaXR0ZWQgZ2FpbiBhdCBhIHNub3cgZGVuc2l0eSBvZiAwLjUwOCAoZy9jbSdeMyonKSBpcyBhcm91bmQgMzguNzYuIFRoZSBjb25maWRlbmNlIGludGVydmFsIG9mICgzNi4yOTYsIDQxLjM5NjMpIHNpZ25pZmllcyB0aGUgcmFuZ2UgaW4gd2hpY2ggdGhlIHRydWUgcG9wdWxhdGlvbiBwYXJhbWV0ZXIgbGllcyBhdCBhIDk1JSBsZXZlbCBvZiBjb25maWRlbmNlLgoKIyBDb25zdHJ1Y3QgUHJlZGljdGlvbiBJbnRlcnZhbCBmb3IgZGVuc2l0eSA9IDAuNTA4CmxvZ19wcmVkaWN0aW9uID0gcHJlZGljdChsZWFzdC5zcXVhcmVzLCBuZXcuZGF0YSwgaW50ZXJ2YWw9InByZWRpY3Rpb24iKQpsb2dfcHJlZGljdGlvbgpwcmVkaWN0aW9uIDwtIGV4cChsb2dfcHJlZGljdGlvbikKcHJlZGljdGlvbgojIEludGVycHJldGF0aW9uOiBGcm9tIHRoZSBvdXRwdXQsIHRoZSBmaXR0ZWQgZ2FpbiBhdCBhIHNub3cgZGVuc2l0eSBvZiAwLjUwOCAoZy9jbSdeMyonKSBpcyBhcm91bmQgMzguNzYuIFRoZSBwcmVkaWN0aW9uIGludGVydmFsIGlzICgzMi43NTQ0LCA0NS44NzIzMSkuCgojIENvbnN0cnVjdCBDb25maWRlbmNlIEludGVydmFsIGZvciBkZW5zaXR5ID0gMC4wMDEKbmV3LmRhdGEgPC0gZGF0YS5mcmFtZShkZW5zaXR5ID0gMC4wMDEpCmxvZ19wcmVkaWN0aW9uID0gcHJlZGljdChsZWFzdC5zcXVhcmVzLCBuZXcuZGF0YSwgaW50ZXJ2YWw9ImNvbmZpZGVuY2UiKQpsb2dfcHJlZGljdGlvbgpwcmVkaWN0aW9uIDwtIGV4cChsb2dfcHJlZGljdGlvbikKcHJlZGljdGlvbgojIEludGVycHJldGF0aW9uOiBGcm9tIHRoZSBvdXRwdXQsIHRoZSBmaXR0ZWQgZ2FpbiBhdCBhIHNub3cgZGVuc2l0eSBvZiAwLjUwOCAoZy9jbSdeMyonKSBpcyBhcm91bmQgNDAwLjQ3ODMuIFRoZSBjb25maWRlbmNlIGludGVydmFsIG9mICgzNjUuMzY0NywgNDM4Ljk2NjUpIHNpZ25pZmllcyB0aGUgcmFuZ2UgaW4gd2hpY2ggdGhlIHRydWUgcG9wdWxhdGlvbiBwYXJhbWV0ZXIgbGllcyBhdCBhIDk1JSBsZXZlbCBvZiBjb25maWRlbmNlLgoKIyBDb25zdHJ1Y3QgUHJlZGljdGlvbiBJbnRlcnZhbCBmb3IgZGVuc2l0eSA9IDAuMDAxCmxvZ19wcmVkaWN0aW9uID0gcHJlZGljdChsZWFzdC5zcXVhcmVzLCBuZXcuZGF0YSwgaW50ZXJ2YWw9InByZWRpY3Rpb24iKQpsb2dfcHJlZGljdGlvbgpwcmVkaWN0aW9uIDwtIGV4cChsb2dfcHJlZGljdGlvbikKcHJlZGljdGlvbgojIEludGVycHJldGF0aW9uOiBGcm9tIHRoZSBvdXRwdXQsIHRoZSBmaXR0ZWQgZ2FpbiBhdCBhIHNub3cgZGVuc2l0eSBvZiAwLjUwOCAoZy9jbSdeMyonKSBpcyBhcm91bmQgNDAwLjQ3ODMuIFRoZSBwcmVkaWN0aW9uIGludGVydmFsIGlzICgzMzQuNDUwOCwgNDc5LjU0MSkuCgpgYGAKCgojIyBTY2VuYXJpbyAzOiBDcm9zcy1WYWxpZGF0aW9uClRvIGNoZWNrIGhvdyB3ZWxsIHlvdXIgcHJvY2VkdXJlIHdvcmtzLCBvbWl0IHRoZSBzZXQgb2YgbWVhc3VyZW1lbnRzIGNvcnJlc3BvbmRpbmcgdG8gdGhlIGJsb2NrIG9mIGRlbnNpdHkgMC41MDgsIGFwcGx5IHlvdXIgImVzdGltYXRpb24iL2NhbGlicmF0aW9uIHByb2NlZHVyZSB0byB0aGUgcmVtYWluaW5nIGRhdGEsIGFuZCBwcm92aWRlIGFuIGludGVydmFsIGVzdGltYXRlIGZvciB0aGUgZGVuc2l0eSBvZiBhIGJsb2NrIHdpdGggYW4gYXZlcmFnZSByZWFkaW5nIG9mIDM4LjYuIFdoZXJlIGRvZXMgdGhlIGFjdHVhbCBkZW5zaXR5IGZhbGwgaW4gdGhlIGludGVydmFsPyBUcnkgdGhlIHNhbWUgdGVzdCwgZm9yIHRoZSBzZXQgb2YgbWVhc3VyZW1lbnRzIGF0IHRoZSAwLjAwMSBkZW5zaXR5LgpgYGB7cn0KCmBgYAoKCiMjIEFkZGl0aW9uYWwgU2NlbmFyaW86IFRPRE8gVGl0bGUKVXNlIHRoZSBhZGRpdGlvbmFsIGRhdGFzZXQgdG8gY29uc3RydWN0IGEgbW9kZWwgZml0dGluZyB0ZW1wZXJhdHVyZSB3aXRoIERPWSwgbGF0aXR1ZGUsIGFuZCBvdGhlciByZWFzb25hYmxlIGZlYXR1cmVzLiBUcnkgc2tldGNoaW5nIHRoZSBsZWFzdCBzcXVhcmVzIGxpbmUgb24gYSBzY2F0dGVyIHBsb3QuIFdlIGFpbSB0byBpbnZlc3RpZ2F0ZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGVtcGVyYXR1cmUgYW5kIHRoZSBET1ksIGFuZCBpdHMgTGF0aXR1ZGUuCmBgYHtyfQojIENoZWNrIHRoZSBjb3JyZWxhdGlvbgpkYXRhIDwtIHJlYWQuY3N2KCdGdWxsIFJlc29sdXRpb24gRGF0YS82NDUwNjQyMC5jc3YnLCBoZWFkZXI9VFJVRSkKZGF0YSA8LSBkYXRhWyxjKCdIb3VyJywnRE9ZJywnUE9TX0RPWScsJ0xhdCcsJ0xvbicsJ1RzJywnQlAnKV0KCiMgRHJvcCB0aGUgZXh0cmVtZSBvdXRsaWVyIGNhc2UKI2RhdGEgPC0gZGF0YVt3aGljaChkYXRhJFRzPi0yMDApLF0KZGF0YV9tYXRyaXggPC0gYXMubWF0cml4KGRhdGEpCgojIENvcnJlbGF0aW9uIE1hdHJpeApjb3JyX21hdHJpeCA8LSBjb3IoZGF0YV9tYXRyaXgpCmNvcnJfbWF0cml4CmBgYApgYGB7cn0KIyBsZWFzdCBzcXVhcmVzIGxpbmUKZml0PC1sbShmb3JtdWxhID0gVHMgfiBET1kgKyBMYXQsIGRhdGEgPSBkYXRhKQpzdW1tYXJ5KGZpdCkKCmdncGxvdChkYXRhLGFlcyh4PURPWSwgeT1UcykpICsgCiAgZ2VvbV9wb2ludChjb2xvcj0nIzI5ODBCOScsIHNpemUgPSA0KSArIAogIGdlb21fc21vb3RoKG1ldGhvZD1sbSwgY29sb3I9JyMyQzNFNTAnKQoKZ2dwbG90KGRhdGEsYWVzKHg9TGF0LCB5PVRzKSkgKyAKICBnZW9tX3BvaW50KGNvbG9yPScjMjk4MEI5Jywgc2l6ZSA9IDQpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kPWxtLCBjb2xvcj0nIzJDM0U1MCcpCgp0aXRsZS5yZXNpZHVhbHMxIDwtICdSZXNpZHVhbHMgb2YgTGVhc3QgU3F1YXJlcyBSZWdyZXNzaW9uIExpbmUnCnBsb3QoZml0JHJlc2lkdWFscywgbWFpbj10aXRsZS5yZXNpZHVhbHMxKQphYmxpbmUoMCwgMCwgY29sPSdyZWQnKQoKbnVtLmJpbnMgPC0gMTAKaGlzdChmaXQkcmVzaWR1YWxzLCBicmVha3M9bnVtLmJpbnMsIG1haW49dGl0bGUucmVzaWR1YWxzMSwgeGxhYj0nVGVtcGVyYXR1cmUnLCBjb2w9J3JlZCcpCgpxcW5vcm0oZml0JHJlc2lkdWFscywgbWFpbj1wYXN0ZSgnTm9ybWFsIFEtUSBQbG90IHdpdGgnLCB0aXRsZS5yZXNpZHVhbHMxKSwgY2V4Lm1haW49MSkKcXFsaW5lKGZpdCRyZXNpZHVhbHMsIGNvbD0ncmVkJykKYGBgCgpgYGB7cn0KIyBBdHRlbXB0IGZvciBNdWx0aXBsZSBSZWdyZXNzaW9ucwpkYXRhJE1pZG5pZ2h0cyA8LSAwCmRhdGEkTWlkbmlnaHRzW3doaWNoKGRhdGEkSG91cjw2KV0gPC0gMQpkYXRhJE1vcm5pbmdzIDwtIDAKZGF0YSRNb3JuaW5nc1t3aGljaChkYXRhJEhvdXI+PTYgJiBkYXRhJEhvdXI8MTEpXSA8LSAxIApkYXRhJE5vb24gPC0gMApkYXRhJE5vb25bd2hpY2goZGF0YSRIb3VyPj0xMSAmIGRhdGEkSG91cjwxNSldIDwtIDEKZGF0YSRBZnRlcm5vb24gPC0gMApkYXRhJEFmdGVybm9vblt3aGljaChkYXRhJEhvdXI+PTE1ICYgZGF0YSRIb3VyPDIwKV0gPC0gMQpkYXRhJE5pZ2h0cyA8LSAwCmRhdGEkTmlnaHRzW3doaWNoKGRhdGEkSG91cj49MjApXSA8LSAxCmBgYA==
=======
LS0tCnRpdGxlOiAnQ0FTRSBTVFVEWSA0OicKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKVGhpcyBzdHVkeSBhbGxvd3MgdXMgdG8gcmV2aXNpdC9yZW5ldwoKMS4gUmVncmVzc2lvbiBtb2RlbGluZwoyLiBQcm9wZXJ0aWVzIG9mIExlYXN0IFNxdWFyZXMvRml0dGluZyAiYSBsaW5lIgozLiBNdWx0aXBsZSBvYnNlcnZhdGlvbgoKRGF0YXNldHMgZm9yIHRoaXMgc3R1ZHkgYXJlCgoxLiBUaGUgbWFpbiBmaWxlOiBnYXVnZS50eHQKMi4gU3VwcGxlbWVudGFyeSBsYXJnZS1zY2FsZSBmaWxlczogZG93bmxvYWQgdGhlIGZvbGxvd2luZyBmb2xkZXIgRnVsbCBSZXNvbHV0aW9uIERhdGEuemlwIE1vcmUgaW5mb3JtYXRpb24gYWJvdXQgdGhlIHN1cHBsZW1lbnRhcnkgZmlsZSBjYW4gYmUgZm91bmQgYXQgaHR0cDovL2lhYnAuYXBsLndhc2hpbmd0b24uZWR1L2RhdGEuaHRtbCBhcyB3ZWxsIGFzIGh0dHA6Ly9uc2lkYy5vcmcvZGF0YS9HMDA3OTEKCgojIyBRdWVzdGlvbgpUaGUgYWltIG9mIHRoaXMgbGFiIGlzIHRvIHByb3ZpZGUgYSBzaW1wbGUgcHJvY2VkdXJlIGZvciBjb252ZXJ0aW5nIGdhaW4gaW50byBkZW5zaXR5IHdoZW4gdGhlIGdhdWdlIGlzIGluIG9wZXJhdGlvbi4gS2VlcCBpbiBtaW5kIHRoYXQgdGhlIGV4cGVyaW1lbnQgd2FzIGNvbmR1Y3RlZCBieSB2YXJ5aW5nIGRlbnNpdHkgYW5kIG1lYXN1cmluZyB0aGUgcmVzcG9uc2UgaW4gZ2FpbiwgYnV0IHdoZW4gdGhlIGdhdWdlIGlzIHVsdGltYXRlbHkgaW4gdXNlLCB0aGUgc25vdy1wYWNrIGRlbnNpdHkgaXMgdG8gYmUgZXN0aW1hdGVkIGZyb20gdGhlIG1lYXN1cmVkIGdhaW4uCgoKIyMgU2V0dXAKYGBge3J9CmRmIDwtIHJlYWQudGFibGUoJ2dhdWdlLTF3YjF3YTYtMmdwZWw0MS50eHQnLCBoZWFkZXI9VFJVRSkKZGYgPC0gZGZbb3JkZXIoZGYkZGVuc2l0eSksIF0gICMgU29ydCBmcm9tIGxlYXN0IHRvIGdyZWF0ZXN0IGRlbnNpdHkKCm0gPC0gOSAgIyBOdW1iZXIgb2YgZGlzdGluY3QgYmxvY2sgZGVuc2l0aWVzCnQgPC0gMTAgICMgTnVtYmVyIG9mIHJlcGxpY2F0ZSBtZWFzdXJlbWVudHMKCiNpbnN0YWxsLnBhY2thZ2VzKCdMMXBhY2snKQojaW5zdGFsbC5wYWNrYWdlcygicXVhbnRyZWciKQpsaWJyYXJ5KEwxcGFjaykgICMgVXNlZCBmb3IgbGVhc3QgYWJzb2x1dGUgZGV2aWF0aW9ucyByZWdyZXNzaW9uIGxpbmUKbGlicmFyeShxdWFudHJlZykgICMgVXNlZCBmb3IgcXVhbnRpbGUgcmVncmVzc2lvbiBsaW5lCmBgYAoKCiMjIFNjZW5hcmlvIDE6IEZpdHRpbmcKVXNlIHRoZSBkYXRhIHRvIGZpdCB0aGUgZ2Fpbiwgb3IgYSB0cmFuc2Zvcm1hdGlvbiBvZiBnYWluLCB0byBkZW5zaXR5LiBUcnkgc2tldGNoaW5nIHRoZSBsZWFzdCBzcXVhcmVzIGxpbmUgb24gYSBzY2F0dGVyIHBsb3QuCgoqIERvIHRoZSByZXNpZHVhbHMgaW5kaWNhdGUgYW55IHByb2JsZW1zIHdpdGggdGhlIGZpdD8KKiBJZiB0aGUgZGVuc2l0aWVzIG9mIHRoZSBwb2x5ZXRoeWxlbmUgYmxvY2tzIGFyZSBub3QgcmVwb3J0ZWQgZXhhY3RseSwgaG93IG1pZ2h0IHRoaXMgYWZmZWN0IHRoZSBmaXQ/CiogV2hhdCBpZiB0aGUgYmxvY2tzIG9mIHBvbHlldGh5bGVuZSB3ZXJlIG5vdCBtZWFzdXJlZCBpbiByYW5kb20gb3JkZXIgKGxvY2F0aW9uKT8KYGBge3J9CiMgUGxvdCByYXcgZGF0YQp0aXRsZSA8LSAnRGVuc2l0eSB2cy4gR2FpbicKeC5heGlzIDwtIGV4cHJlc3Npb24oJ0RlbnNpdHkgKGcvY20nXjMqJyknKQp5LmF4aXMgPC0gJ0dhaW4nCngucmFuZ2UgPC0gYygwLCAuNykKeS5yYW5nZSA8LSBjKDIuNSwgNikKcGxvdChkZiwgbWFpbj10aXRsZSwgeGxhYj14LmF4aXMsIHlsYWI9eS5heGlzLCB4bGltPXgucmFuZ2UpCgoKIyBUYWtlIGxvZyB0cmFuc2Zvcm1hdGlvbiBvZiByZXNwb25zZSB2YXJpYWJsZSAoZ2FpbikKeS5sb2cuYXhpcyA9ICdsb2coR2FpbiknCmRmLmxvZyA9IGRhdGEuZnJhbWUoZGZbJ2RlbnNpdHknXSwgbG9nKGRmWydnYWluJ10pKQpwbG90KGRmLmxvZywgbWFpbj10aXRsZSwgeGxhYj14LmF4aXMsIHlsYWI9eS5sb2cuYXhpcywgeGxpbT14LnJhbmdlLCB5bGltPXkucmFuZ2UpCgoKIyBBdmVyYWdlIHJlcGxpY2F0ZSBtZWFzdXJlbWVudHMKZGYubG9nLmF2ZyA9IGFnZ3JlZ2F0ZShsaXN0KGdhaW49ZGYubG9nJGdhaW4pLCBieT1saXN0KGRlbnNpdHk9ZGYubG9nJGRlbnNpdHkpLCBGVU49bWVhbikKcGxvdChkZi5sb2cuYXZnLCBtYWluPXRpdGxlLCB4bGFiPXguYXhpcywgeWxhYj15LmxvZy5heGlzLCB4bGltPXgucmFuZ2UsIHlsaW09eS5yYW5nZSkKCgojIEZpdCBnYWluIHRvIGRlbnNpdHkKY29yKGRmLmxvZy5hdmcpCgpsZWFzdC5zcXVhcmVzIDwtIGxtKGdhaW5+ZGVuc2l0eSwgZGF0YT1kZi5sb2cuYXZnKQpsYWQgPC0gbGFkKGdhaW5+ZGVuc2l0eSwgZGF0YT1kZi5sb2cuYXZnKQpxdWFudCA8LSBycShnYWlufmRlbnNpdHksIHRhdT0uNSwgZGF0YT1kZi5sb2cuYXZnKQoKcGxvdChkZi5sb2csIG1haW49dGl0bGUsIHhsYWI9eC5heGlzLCB5bGFiPXkubG9nLmF4aXMsIHhsaW09eC5yYW5nZSwgeWxpbT15LnJhbmdlKQphYmxpbmUobGVhc3Quc3F1YXJlcywgY29sPSdyZWQnKQphYmxpbmUobGFkLCBjb2w9J2JsdWUnKQphYmxpbmUocXVhbnQsIGNvbD0nZ3JlZW4nKQpsZWdlbmQoJ3RvcHJpZ2h0JywgbGVnZW5kPWMoJ0xlYXN0IFNxdWFyZXMgUmVncmVzc2lvbiBMaW5lJywgJ0xlYXN0IEFic29sdXRlIERldmlhdGlvbnMgUmVncmVzc2lvbiBMaW5lJywgJzUwJSBRdWFudGlsZSBSZWdyZXNzaW9uIExpbmUnKSwgY29sPWMoJ3JlZCcsICdibHVlJywgJ2dyZWVuJyksIGx0eT0xKQoKc3VtbWFyeShsZWFzdC5zcXVhcmVzKQpzdW1tYXJ5KGxhZCkKcXVhbnQKCgojIENoZWNrIGNvbmRpdGlvbnMgZm9yIGxpbmVhciByZWdyZXNzaW9uOiBsaW5lYXJpdHksIG5vcm1hbGl0eSBvZiByZXNpZHVhbHMsIGFuZCBjb25zdGFudCB2YXJpYWJpbGl0eQpsZWFzdC5zcXVhcmVzLnJlc2lkdWFscyA8LSBkYXRhLmZyYW1lKGRmLmxvZ1snZGVuc2l0eSddLCBkZi5sb2dbJ2dhaW4nXSAtIHJlcChwcmVkaWN0KGxlYXN0LnNxdWFyZXMpLCBlYWNoPTEwKSkKbGFkLnJlc2lkdWFscyA8LSBkYXRhLmZyYW1lKGRmLmxvZ1snZGVuc2l0eSddLCBkZi5sb2dbJ2dhaW4nXSAtIHJlcChwcmVkaWN0KGxhZCksIGVhY2g9MTApKQpxdWFudC5yZXNpZHVhbHMgPC0gZGF0YS5mcmFtZShkZi5sb2dbJ2RlbnNpdHknXSwgZGYubG9nWydnYWluJ10gLSByZXAocHJlZGljdChxdWFudCksIGVhY2g9MTApKQoKdGl0bGUucmVzaWR1YWxzMSA8LSAnUmVzaWR1YWxzIG9mIExlYXN0IFNxdWFyZXMgUmVncmVzc2lvbiBMaW5lJwp0aXRsZS5yZXNpZHVhbHMyIDwtICdSZXNpZHVhbHMgb2YgTGVhc3QgQWJzb2x1dGUgRGV2aWF0aW9ucyBSZWdyZXNzaW9uIExpbmUnCnRpdGxlLnJlc2lkdWFsczMgPC0gJ1Jlc2lkdWFscyBvZiA1MCUgUXVhbnRpbGUgUmVncmVzc2lvbiBMaW5lJwpwbG90KGxlYXN0LnNxdWFyZXMucmVzaWR1YWxzJGdhaW4sIG1haW49dGl0bGUucmVzaWR1YWxzMSwgeWxhYj15LmF4aXMpCmFibGluZSgwLCAwLCBjb2w9J3JlZCcpCnBsb3QobGFkLnJlc2lkdWFscyRnYWluLCBtYWluPXRpdGxlLnJlc2lkdWFsczIsIHlsYWI9eS5heGlzKQphYmxpbmUoMCwgMCwgY29sPSdibHVlJykKcGxvdChxdWFudC5yZXNpZHVhbHMkZ2FpbiwgbWFpbj10aXRsZS5yZXNpZHVhbHMzLCB5bGFiPXkuYXhpcykKYWJsaW5lKDAsIDAsIGNvbD0nZ3JlZW4nKQoKbnVtLmJpbnMgPC0gMTIKaGlzdChsZWFzdC5zcXVhcmVzLnJlc2lkdWFscyRnYWluLCBicmVha3M9bnVtLmJpbnMsIG1haW49dGl0bGUucmVzaWR1YWxzMSwgeGxhYj15LmF4aXMsIGNvbD0ncmVkJykKaGlzdChsYWQucmVzaWR1YWxzJGdhaW4sIGJyZWFrcz1udW0uYmlucywgbWFpbj10aXRsZS5yZXNpZHVhbHMyLCB4bGFiPXkuYXhpcywgY29sPSdibHVlJykKaGlzdChxdWFudC5yZXNpZHVhbHMkZ2FpbiwgYnJlYWtzPW51bS5iaW5zLCBtYWluPXRpdGxlLnJlc2lkdWFsczMsIHhsYWI9eS5heGlzLCBjb2w9J2dyZWVuJykKCnFxbm9ybShsZWFzdC5zcXVhcmVzLnJlc2lkdWFscyRnYWluLCBtYWluPXBhc3RlKCdOb3JtYWwgUS1RIFBsb3Qgd2l0aCcsIHRpdGxlLnJlc2lkdWFsczEpLCBjZXgubWFpbj0xKQpxcWxpbmUobGVhc3Quc3F1YXJlcy5yZXNpZHVhbHMkZ2FpbiwgY29sPSdyZWQnKQpxcW5vcm0obGFkLnJlc2lkdWFscyRnYWluLCBtYWluPXBhc3RlKCdOb3JtYWwgUS1RIFBsb3Qgd2l0aCcsIHRpdGxlLnJlc2lkdWFsczIpLCBjZXgubWFpbj0xKQpxcWxpbmUobGFkLnJlc2lkdWFscyRnYWluLCBjb2w9J2JsdWUnKQpxcW5vcm0ocXVhbnQucmVzaWR1YWxzJGdhaW4sIG1haW49cGFzdGUoJ05vcm1hbCBRLVEgUGxvdCB3aXRoJywgdGl0bGUucmVzaWR1YWxzMyksIGNleC5tYWluPTEpCnFxbGluZShxdWFudC5yZXNpZHVhbHMkZ2FpbiwgY29sPSdncmVlbicpCmBgYAoKCiMjIFNjZW5hcmlvIDI6IFByZWRpY3RpbmcKVWx0aW1hdGVseSB3ZSBhcmUgaW50ZXJlc3RlZCBpbiBhbnN3ZXJpbmcgcXVlc3Rpb25zIHN1Y2ggYXM6IEdpdmVuIGEgZ2FpbiByZWFkaW5nIG9mIDM4LjYsIHdoYXQgaXMgdGhlIGRlbnNpdHkgb2YgdGhlIHNub3ctcGFjaz8gR2l2ZW4gYSBnYWluIHJlYWRpbmcgb2YgNDI2LjcsIHdoYXQgaXMgdGhlIGRlbnNpdHkgb2YgdGhlIHNub3ctcGFjaz8gVGhlc2UgdHdvIG51bWVyaWMgdmFsdWVzLCAzOC42IGFuZCA0MjYuNywgd2VyZSBjaG9zZW4gYmVjYXVzZSB0aGV5IGFyZSB0aGUgYXZlcmFnZSBnYWlucyBmb3IgdGhlIDAuNTA4IGFuZCAwLjAwMSBkZW5zaXRpZXMsIHJlc3BlY3RpdmVseS4KCiogRGV2ZWxvcCBhIHByb2NlZHVyZSBmb3IgYWRkaW5nIGJhbmRzIGFyb3VuZCB5b3VyIGxlYXN0IHNxdWFyZXMgbGluZSB0aGF0IGNhbiBiZSB1c2VkIHRvIG1ha2UgaW50ZXJ2YWwgZXN0aW1hdGVzIGZvciB0aGUgc25vdy1wYWNrIGRlbnNpdHkgZnJvbSBnYWluIG1lYXN1cmVtZW50cy4gS2VlcCBpbiBtaW5kIGhvdyB0aGUgZGF0YSB3ZXJlIGNvbGxlY3RlZDogc2V2ZXJhbCBtZWFzdXJlbWVudHMgb2YgZ2FpbiB3ZXJlIHRha2VuIGZvciBwb2x5ZW55dGh5bGVuZSBibG9ja3Mgb2Yga25vd24gZGVuc2l0eS4KYGBge3IgZmlnLmFzcD0yLCBmaWcud2lkdGg9NX0KIyBQcmVkaWN0aW9ucwpQcmVkaWN0TG9nR2FpbiA8LSBmdW5jdGlvbihkZW5zaXR5KQogIHByZWRpY3QobGVhc3Quc3F1YXJlcywgZGF0YS5mcmFtZShkZW5zaXR5PWRlbnNpdHkpKSAgIyBQcmVkaWN0IGxvZyhnYWluKSB1c2luZyBkZW5zaXR5CgpQcmVkaWN0RGVuc2l0eUxlYXN0U3F1YXJlcyA8LSBmdW5jdGlvbihnYWluKSB7CiAgaW50ZXJjZXB0IDwtIGNvZWYobGVhc3Quc3F1YXJlcylbWzFdXQogIHNsb3BlIDwtIGNvZWYobGVhc3Quc3F1YXJlcylbWzJdXQogIChsb2coZ2FpbikgLSBpbnRlcmNlcHQpIC8gc2xvcGUgICMgUHJlZGljdCBkZW5zaXR5IHVzaW5nIGdhaW4KfQoKUHJlZGljdERlbnNpdHlMYWQgPC0gZnVuY3Rpb24oZ2FpbikgewogIGludGVyY2VwdCA8LSBjb2VmKGxhZClbWzFdXQogIHNsb3BlIDwtIGNvZWYobGFkKVtbMl1dCiAgKGxvZyhnYWluKSAtIGludGVyY2VwdCkgLyBzbG9wZSAgIyBQcmVkaWN0IGRlbnNpdHkgdXNpbmcgZ2Fpbgp9CgpQcmVkaWN0RGVuc2l0eVF1YW50IDwtIGZ1bmN0aW9uKGdhaW4pIHsKICBpbnRlcmNlcHQgPC0gY29lZihxdWFudClbWzFdXQogIHNsb3BlIDwtIGNvZWYocXVhbnQpW1syXV0KICAobG9nKGdhaW4pIC0gaW50ZXJjZXB0KSAvIHNsb3BlICAjIFByZWRpY3QgZGVuc2l0eSB1c2luZyBnYWluCn0KCgojIDk1JSBwcmVkaWN0aW9uIGFuZCBjb25maWRlbmNlIGludGVydmFscyBvZiBsb2coZ2FpbikgdXNpbmcgZGVuc2l0eQp0IDwtIHF0KC45NzUsIGRmPW0tMikKbWVhbi5kZW5zaXR5IDwtIG1lYW4oZGYubG9nLmF2ZyRkZW5zaXR5KQpzdW1tYXRpb24gPC0gc3VtKChkZi5sb2cuYXZnJGRlbnNpdHkgLSBtZWFuLmRlbnNpdHkpIF4gMikKCnMyIDwtIGFnZ3JlZ2F0ZShsaXN0KHZhcmlhbmNlPWxlYXN0LnNxdWFyZXMucmVzaWR1YWxzJGdhaW4pLCBieT1saXN0KGRlbnNpdHk9bGVhc3Quc3F1YXJlcy5yZXNpZHVhbHMkZGVuc2l0eSksIEZVTj12YXIpCnMucG9vbGVkIDwtIHNxcnQobWVhbihzMiR2YXJpYW5jZSkpCgpjZW50ZXIuZXhwciA8LSBxdW90ZShjZW50ZXIgPC0gUHJlZGljdExvZ0dhaW4oZGVuc2l0eSkpCmNpLndpZHRoLmV4cHIgPC0gcXVvdGUod2lkdGggPC0gdCAqIHMucG9vbGVkICogc3FydCgxL20gKyAoZGVuc2l0eS1tZWFuLmRlbnNpdHkpXjIgLyBzdW1tYXRpb24pKQpwaS53aWR0aC5leHByIDwtIHF1b3RlKHdpZHRoIDwtIHQgKiBzLnBvb2xlZCAqIHNxcnQoMSArIDEvbSArIChkZW5zaXR5LW1lYW4uZGVuc2l0eSleMiAvIHN1bW1hdGlvbikpCgpMb2dHYWluQ2lMb3dlciA8LSBmdW5jdGlvbihkZW5zaXR5KSB7CiAgZXZhbChjZW50ZXIuZXhwcikKICBldmFsKGNpLndpZHRoLmV4cHIpCiAgY2VudGVyIC0gd2lkdGgKfQoKTG9nR2FpbkNpVXBwZXIgPC0gZnVuY3Rpb24oZGVuc2l0eSkgewogIGV2YWwoY2VudGVyLmV4cHIpCiAgZXZhbChjaS53aWR0aC5leHByKQogIGNlbnRlciArIHdpZHRoCn0KCkxvZ0dhaW5QaUxvd2VyIDwtIGZ1bmN0aW9uKGRlbnNpdHkpIHsKICBldmFsKGNlbnRlci5leHByKQogIGV2YWwocGkud2lkdGguZXhwcikKICBjZW50ZXIgLSB3aWR0aAp9CgpMb2dHYWluUGlVcHBlciA8LSBmdW5jdGlvbihkZW5zaXR5KSB7CiAgZXZhbChjZW50ZXIuZXhwcikKICBldmFsKHBpLndpZHRoLmV4cHIpCiAgY2VudGVyICsgd2lkdGgKfQoKCiMgQWRkIGJhbmRzIGFyb3VuZCBsZWFzdCBzcXVhcmVzIGxpbmUKcGxvdChkZi5sb2csIG1haW49dGl0bGUsIHhsYWI9eC5heGlzLCB5bGFiPXkubG9nLmF4aXMsIHhsaW09eC5yYW5nZSwgeWxpbT15LnJhbmdlKQphYmxpbmUobGVhc3Quc3F1YXJlcywgY29sPSdyZWQnKQoKY2kuY29sIDwtICdwdXJwbGUnCnBpLmNvbCA8LSAnYmx1ZScKc3ltYm9sIDwtICctJwpzaXplIDwtIDEuNQpsaW5lLnR5cGUgPC0gMwpsaW5lLndpZHRoIDwtIDAuNwoKY29uZmlkZW5jZS5pbnRlcnZhbHMgPC0gZGF0YS5mcmFtZShkZW5zaXR5PWRmLmxvZy5hdmckZGVuc2l0eSwgbG93ZXI9TG9nR2FpbkNpTG93ZXIoZGYubG9nLmF2ZyRkZW5zaXR5KSwgdXBwZXI9TG9nR2FpbkNpVXBwZXIoZGYubG9nLmF2ZyRkZW5zaXR5KSkKcG9pbnRzKHg9Y29uZmlkZW5jZS5pbnRlcnZhbHMkZGVuc2l0eSwgeT1jb25maWRlbmNlLmludGVydmFscyRsb3dlciwgY29sPWNpLmNvbCwgcGNoPXN5bWJvbCwgY2V4PXNpemUpCnBvaW50cyh4PWNvbmZpZGVuY2UuaW50ZXJ2YWxzJGRlbnNpdHksIHk9Y29uZmlkZW5jZS5pbnRlcnZhbHMkdXBwZXIsIGNvbD1jaS5jb2wsIHBjaD1zeW1ib2wsIGNleD1zaXplKQpsaW5lcyh4PWNvbmZpZGVuY2UuaW50ZXJ2YWxzJGRlbnNpdHksIHk9Y29uZmlkZW5jZS5pbnRlcnZhbHMkbG93ZXIsIGNvbD1jaS5jb2wsIGx0eT1saW5lLnR5cGUsIGx3ZD1saW5lLndpZHRoKQpsaW5lcyh4PWNvbmZpZGVuY2UuaW50ZXJ2YWxzJGRlbnNpdHksIHk9Y29uZmlkZW5jZS5pbnRlcnZhbHMkdXBwZXIsIGNvbD1jaS5jb2wsIGx0eT1saW5lLnR5cGUsIGx3ZD1saW5lLndpZHRoKQoKcHJlZGljdGlvbi5pbnRlcnZhbHMgPC0gZGF0YS5mcmFtZShkZW5zaXR5PWRmLmxvZy5hdmckZGVuc2l0eSwgbG93ZXI9TG9nR2FpblBpTG93ZXIoZGYubG9nLmF2ZyRkZW5zaXR5KSwgdXBwZXI9TG9nR2FpblBpVXBwZXIoZGYubG9nLmF2ZyRkZW5zaXR5KSkKcG9pbnRzKHg9cHJlZGljdGlvbi5pbnRlcnZhbHMkZGVuc2l0eSwgeT1wcmVkaWN0aW9uLmludGVydmFscyRsb3dlciwgY29sPXBpLmNvbCwgcGNoPXN5bWJvbCwgY2V4PXNpemUpCnBvaW50cyh4PXByZWRpY3Rpb24uaW50ZXJ2YWxzJGRlbnNpdHksIHk9cHJlZGljdGlvbi5pbnRlcnZhbHMkdXBwZXIsIGNvbD1waS5jb2wsIHBjaD1zeW1ib2wsIGNleD1zaXplKQpsaW5lcyh4PXByZWRpY3Rpb24uaW50ZXJ2YWxzJGRlbnNpdHksIHk9cHJlZGljdGlvbi5pbnRlcnZhbHMkbG93ZXIsIGNvbD1waS5jb2wsIGx0eT1saW5lLnR5cGUsIGx3ZD1saW5lLndpZHRoKQpsaW5lcyh4PXByZWRpY3Rpb24uaW50ZXJ2YWxzJGRlbnNpdHksIHk9cHJlZGljdGlvbi5pbnRlcnZhbHMkdXBwZXIsIGNvbD1waS5jb2wsIGx0eT1saW5lLnR5cGUsIGx3ZD1saW5lLndpZHRoKQoKbGVnZW5kKCd0b3ByaWdodCcsIGxlZ2VuZD1jKCdMZWFzdCBTcXVhcmVzIFJlZ3Jlc3Npb24gTGluZScsICc5NSUgQ29uZmlkZW5jZSBJbnRlcnZhbCBCYW5kcycsICc5NSUgUHJlZGljdGlvbiBJbnRlcnZhbCBCYW5kcycpLCBjb2w9YygncmVkJywgY2kuY29sLCBwaS5jb2wpLCBsdHk9MSkKCgojIDk1JSBwcmVkaWN0aW9uIGFuZCBjb25maWRlbmNlIGludGVydmFscyBvZiBkZW5zaXR5IHVzaW5nIGdhaW4KZW5kLnBvaW50cyA8LSBjKC0xLCAzKSAgIyBJbnRlcnZhbCB0byBzZWFyY2ggdGhlIHJvb3QgaW4KCkRlbnNpdHlDaSA8LSBmdW5jdGlvbihnYWluKSB7CiAgbG93ZXIgPC0gdW5pcm9vdChmdW5jdGlvbihkZW5zaXR5KSBsb2coZ2FpbikgLSBMb2dHYWluQ2lMb3dlcihkZW5zaXR5KSwgaW50ZXJ2YWw9ZW5kLnBvaW50cylbWzFdXQogIHVwcGVyIDwtIHVuaXJvb3QoZnVuY3Rpb24oZGVuc2l0eSkgbG9nKGdhaW4pIC0gTG9nR2FpbkNpVXBwZXIoZGVuc2l0eSksIGludGVydmFsPWVuZC5wb2ludHMpW1sxXV0KICBjKGxvd2VyLCB1cHBlcikKfQoKRGVuc2l0eVBpIDwtIGZ1bmN0aW9uKGdhaW4pIHsKICBsb3dlciA8LSB1bmlyb290KGZ1bmN0aW9uKGRlbnNpdHkpIGxvZyhnYWluKSAtIExvZ0dhaW5QaUxvd2VyKGRlbnNpdHkpLCBlbmQucG9pbnRzKVtbMV1dCiAgdXBwZXIgPC0gdW5pcm9vdChmdW5jdGlvbihkZW5zaXR5KSBsb2coZ2FpbikgLSBMb2dHYWluUGlVcHBlcihkZW5zaXR5KSwgZW5kLnBvaW50cylbWzFdXQogIGMobG93ZXIsIHVwcGVyKQp9CgoKIyBQb2ludCBhbmQgaW50ZXJ2YWwgZXN0aW1hdGVzIGZvciBleGFtcGxlIGdhaW4gcmVhZGluZ3MKUHJlZGljdERlbnNpdHlMZWFzdFNxdWFyZXMoMzguNikgICMgMzguNiBpcyB0aGUgYXZlcmFnZSBnYWluIGZvciAwLjUwOCBkZW5zaXR5ClByZWRpY3REZW5zaXR5TGFkKDM4LjYpClByZWRpY3REZW5zaXR5UXVhbnQoMzguNikKRGVuc2l0eUNpKDM4LjYpCkRlbnNpdHlQaSgzOC42KQoKUHJlZGljdERlbnNpdHlMZWFzdFNxdWFyZXMoNDI2LjcpICAjIDQyNi43IGlzIHRoZSBhdmVyYWdlIGdhaW4gZm9yIDAuMDAxIGRlbnNpdHkKUHJlZGljdERlbnNpdHlMYWQoNDI2LjcpClByZWRpY3REZW5zaXR5UXVhbnQoMzguNikKRGVuc2l0eUNpKDQyNi43KQpEZW5zaXR5UGkoNDI2LjcpCmBgYAoKCiMjIFNjZW5hcmlvIDM6IENyb3NzLVZhbGlkYXRpb24KVG8gY2hlY2sgaG93IHdlbGwgeW91ciBwcm9jZWR1cmUgd29ya3MsIG9taXQgdGhlIHNldCBvZiBtZWFzdXJlbWVudHMgY29ycmVzcG9uZGluZyB0byB0aGUgYmxvY2sgb2YgZGVuc2l0eSAwLjUwOCwgYXBwbHkgeW91ciAiZXN0aW1hdGlvbiIvY2FsaWJyYXRpb24gcHJvY2VkdXJlIHRvIHRoZSByZW1haW5pbmcgZGF0YSwgYW5kIHByb3ZpZGUgYW4gaW50ZXJ2YWwgZXN0aW1hdGUgZm9yIHRoZSBkZW5zaXR5IG9mIGEgYmxvY2sgd2l0aCBhbiBhdmVyYWdlIHJlYWRpbmcgb2YgMzguNi4gV2hlcmUgZG9lcyB0aGUgYWN0dWFsIGRlbnNpdHkgZmFsbCBpbiB0aGUgaW50ZXJ2YWw/IFRyeSB0aGUgc2FtZSB0ZXN0LCBmb3IgdGhlIHNldCBvZiBtZWFzdXJlbWVudHMgYXQgdGhlIDAuMDAxIGRlbnNpdHkuCmBgYHtyIGZpZy5hc3A9MiwgZmlnLndpZHRoPTV9CmZvciAob21pdHRlZCBpbiBjKDAuNTA4LCAwLjAwMSkpIHsKICAjIE9taXQgbWVhc3VyZW1lbnRzIGNvcnJlc3BvbmRpbmcgdG8gdGhlIHNwZWNpZmllZCBkZW5zaXR5CiAgZGYubG9nLm9taXR0ZWQgPSBkZi5sb2dbd2hpY2goZGYubG9nWydkZW5zaXR5J10gIT0gb21pdHRlZCksIF0KICBkZi5sb2cuYXZnLm9taXR0ZWQgPC0gZGYubG9nLmF2Z1t3aGljaChkZi5sb2cuYXZnWydkZW5zaXR5J10gIT0gb21pdHRlZCksIF0KICAKICAKICAjIFJlZG8gY2FsY3VsYXRpb25zIHVzaW5nIG1vZGlmaWVkIGRhdGFzZXQKICBsZWFzdC5zcXVhcmVzIDwtIGxtKGdhaW5+ZGVuc2l0eSwgZGF0YT1kZi5sb2cuYXZnLm9taXR0ZWQpCiAgCiAgbWVhbi5kZW5zaXR5IDwtIG1lYW4oZGYubG9nLmF2Zy5vbWl0dGVkJGRlbnNpdHkpCiAgc3VtbWF0aW9uIDwtIHN1bSgoZGYubG9nLmF2Zy5vbWl0dGVkJGRlbnNpdHkgLSBtZWFuLmRlbnNpdHkpIF4gMikKICAKICBzMiA8LSBhZ2dyZWdhdGUobGlzdCh2YXJpYW5jZT1sZWFzdC5zcXVhcmVzLnJlc2lkdWFscyRnYWluKSwgYnk9bGlzdChkZW5zaXR5PWxlYXN0LnNxdWFyZXMucmVzaWR1YWxzJGRlbnNpdHkpLCBGVU49dmFyKQogIHMucG9vbGVkIDwtIHNxcnQobWVhbihzMiR2YXJpYW5jZSkpCiAgCiAgY2kud2lkdGguZXhwciA8LSBxdW90ZSh3aWR0aCA8LSB0ICogcy5wb29sZWQgKiBzcXJ0KDEvKG0tMSkgKyAoZGVuc2l0eS1tZWFuLmRlbnNpdHkpXjIgLyBzdW1tYXRpb24pKQogIHBpLndpZHRoLmV4cHIgPC0gcXVvdGUod2lkdGggPC0gdCAqIHMucG9vbGVkICogc3FydCgxICsgMS8obS0xKSArIChkZW5zaXR5LW1lYW4uZGVuc2l0eSleMiAvIHN1bW1hdGlvbikpCiAgCiAgcGxvdChkZi5sb2cub21pdHRlZCwgbWFpbj10aXRsZSwgeGxhYj14LmF4aXMsIHlsYWI9eS5sb2cuYXhpcywgeGxpbT14LnJhbmdlLCB5bGltPXkucmFuZ2UpCiAgYWJsaW5lKGxlYXN0LnNxdWFyZXMsIGNvbD0ncmVkJykKICAKICBjaS5jb2wgPC0gJ3B1cnBsZScKICBwaS5jb2wgPC0gJ2JsdWUnCiAgc3ltYm9sIDwtICctJwogIHNpemUgPC0gMS41CiAgbGluZS50eXBlIDwtIDMKICBsaW5lLndpZHRoIDwtIDAuNwogIAogIGNvbmZpZGVuY2UuaW50ZXJ2YWxzIDwtIGRhdGEuZnJhbWUoZGVuc2l0eT1kZi5sb2cuYXZnLm9taXR0ZWQkZGVuc2l0eSwgbG93ZXI9TG9nR2FpbkNpTG93ZXIoZGYubG9nLmF2Zy5vbWl0dGVkJGRlbnNpdHkpLCB1cHBlcj1Mb2dHYWluQ2lVcHBlcihkZi5sb2cuYXZnLm9taXR0ZWQkZGVuc2l0eSkpCiAgcG9pbnRzKHg9Y29uZmlkZW5jZS5pbnRlcnZhbHMkZGVuc2l0eSwgeT1jb25maWRlbmNlLmludGVydmFscyRsb3dlciwgY29sPWNpLmNvbCwgcGNoPXN5bWJvbCwgY2V4PXNpemUpCiAgcG9pbnRzKHg9Y29uZmlkZW5jZS5pbnRlcnZhbHMkZGVuc2l0eSwgeT1jb25maWRlbmNlLmludGVydmFscyR1cHBlciwgY29sPWNpLmNvbCwgcGNoPXN5bWJvbCwgY2V4PXNpemUpCiAgbGluZXMoeD1jb25maWRlbmNlLmludGVydmFscyRkZW5zaXR5LCB5PWNvbmZpZGVuY2UuaW50ZXJ2YWxzJGxvd2VyLCBjb2w9Y2kuY29sLCBsdHk9bGluZS50eXBlLCBsd2Q9bGluZS53aWR0aCkKICBsaW5lcyh4PWNvbmZpZGVuY2UuaW50ZXJ2YWxzJGRlbnNpdHksIHk9Y29uZmlkZW5jZS5pbnRlcnZhbHMkdXBwZXIsIGNvbD1jaS5jb2wsIGx0eT1saW5lLnR5cGUsIGx3ZD1saW5lLndpZHRoKQogIAogIHByZWRpY3Rpb24uaW50ZXJ2YWxzIDwtIGRhdGEuZnJhbWUoZGVuc2l0eT1kZi5sb2cuYXZnLm9taXR0ZWQkZGVuc2l0eSwgbG93ZXI9TG9nR2FpblBpTG93ZXIoZGYubG9nLmF2Zy5vbWl0dGVkJGRlbnNpdHkpLCB1cHBlcj1Mb2dHYWluUGlVcHBlcihkZi5sb2cuYXZnLm9taXR0ZWQkZGVuc2l0eSkpCiAgcG9pbnRzKHg9cHJlZGljdGlvbi5pbnRlcnZhbHMkZGVuc2l0eSwgeT1wcmVkaWN0aW9uLmludGVydmFscyRsb3dlciwgY29sPXBpLmNvbCwgcGNoPXN5bWJvbCwgY2V4PXNpemUpCiAgcG9pbnRzKHg9cHJlZGljdGlvbi5pbnRlcnZhbHMkZGVuc2l0eSwgeT1wcmVkaWN0aW9uLmludGVydmFscyR1cHBlciwgY29sPXBpLmNvbCwgcGNoPXN5bWJvbCwgY2V4PXNpemUpCiAgbGluZXMoeD1wcmVkaWN0aW9uLmludGVydmFscyRkZW5zaXR5LCB5PXByZWRpY3Rpb24uaW50ZXJ2YWxzJGxvd2VyLCBjb2w9cGkuY29sLCBsdHk9bGluZS50eXBlLCBsd2Q9bGluZS53aWR0aCkKICBsaW5lcyh4PXByZWRpY3Rpb24uaW50ZXJ2YWxzJGRlbnNpdHksIHk9cHJlZGljdGlvbi5pbnRlcnZhbHMkdXBwZXIsIGNvbD1waS5jb2wsIGx0eT1saW5lLnR5cGUsIGx3ZD1saW5lLndpZHRoKQogIAogIGxlZ2VuZCgndG9wcmlnaHQnLCBsZWdlbmQ9YygnTGVhc3QgU3F1YXJlcyBSZWdyZXNzaW9uIExpbmUnLCAnOTUlIENvbmZpZGVuY2UgSW50ZXJ2YWwgQmFuZHMnLCAnOTUlIFByZWRpY3Rpb24gSW50ZXJ2YWwgQmFuZHMnKSwgY29sPWMoJ3JlZCcsIGNpLmNvbCwgcGkuY29sKSwgbHR5PTEpCiAgCiAgcHJpbnQoUHJlZGljdERlbnNpdHlMZWFzdFNxdWFyZXMoMzguNikpICAjIDM4LjYgaXMgdGhlIGF2ZXJhZ2UgZ2FpbiBmb3IgMC41MDggZGVuc2l0eQogIHByaW50KERlbnNpdHlDaSgzOC42KSkKICBwcmludChEZW5zaXR5UGkoMzguNikpCiAgCiAgcHJpbnQoUHJlZGljdERlbnNpdHlMZWFzdFNxdWFyZXMoNDI2LjcpKSAgIyA0MjYuNyBpcyB0aGUgYXZlcmFnZSBnYWluIGZvciAwLjAwMSBkZW5zaXR5CiAgcHJpbnQoRGVuc2l0eUNpKDQyNi43KSkKICBwcmludChEZW5zaXR5UGkoNDI2LjcpKQp9CmBgYAoKCiMjIEFkZGl0aW9uYWwgU2NlbmFyaW86IFRlbXBlcmF0dXJlLCBET1ksIGFuZCBMYXRpdHVkZS4KVXNlIHRoZSBhZGRpdGlvbmFsIGRhdGFzZXQgdG8gY29uc3RydWN0IGEgbW9kZWwgZml0dGluZyB0ZW1wZXJhdHVyZSB3aXRoIERPWSwgbGF0aXR1ZGUsIGFuZCBvdGhlciByZWFzb25hYmxlIGZlYXR1cmVzLiBUcnkgc2tldGNoaW5nIHRoZSBsZWFzdCBzcXVhcmVzIGxpbmUgb24gYSBzY2F0dGVyIHBsb3QuIFdlIGFpbSB0byBpbnZlc3RpZ2F0ZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGVtcGVyYXR1cmUgYW5kIHRoZSBET1ksIGFuZCBpdHMgbGF0aXR1ZGUuCmBgYHtyfQojIENoZWNrIHRoZSBjb3JyZWxhdGlvbgpkYXRhIDwtIHJlYWQuY3N2KCdGdWxsIFJlc29sdXRpb24gRGF0YS82NDUwNjQyMC5jc3YnLCBoZWFkZXI9VFJVRSkKZGF0YSA8LSBkYXRhWyxjKCdIb3VyJywnRE9ZJywnUE9TX0RPWScsJ0xhdCcsJ0xvbicsJ1RzJywnQlAnKV0KCiMgRHJvcCB0aGUgZXh0cmVtZSBvdXRsaWVyIGNhc2UKI2RhdGEgPC0gZGF0YVt3aGljaChkYXRhJFRzPi0yMDApLF0KZGF0YV9tYXRyaXggPC0gYXMubWF0cml4KGRhdGEpCgojIENvcnJlbGF0aW9uIE1hdHJpeApjb3JyX21hdHJpeCA8LSBjb3IoZGF0YV9tYXRyaXgpCmNvcnJfbWF0cml4CmBgYAoKYGBge3J9CiMgbGVhc3Qgc3F1YXJlcyBsaW5lCmZpdDwtbG0oZm9ybXVsYSA9IFRzIH4gRE9ZICsgTGF0LCBkYXRhID0gZGF0YSkKc3VtbWFyeShmaXQpCgpnZ3Bsb3QoZGF0YSxhZXMoeD1ET1ksIHk9VHMpKSArIAogIGdlb21fcG9pbnQoY29sb3I9JyMyOTgwQjknLCBzaXplID0gNCkgKyAKICBnZW9tX3Ntb290aChtZXRob2Q9bG0sIGNvbG9yPScjMkMzRTUwJykKCmdncGxvdChkYXRhLGFlcyh4PUxhdCwgeT1UcykpICsgCiAgZ2VvbV9wb2ludChjb2xvcj0nIzI5ODBCOScsIHNpemUgPSA0KSArIAogIGdlb21fc21vb3RoKG1ldGhvZD1sbSwgY29sb3I9JyMyQzNFNTAnKQoKdGl0bGUucmVzaWR1YWxzMSA8LSAnUmVzaWR1YWxzIG9mIExlYXN0IFNxdWFyZXMgUmVncmVzc2lvbiBMaW5lJwpwbG90KGZpdCRyZXNpZHVhbHMsIG1haW49dGl0bGUucmVzaWR1YWxzMSkKYWJsaW5lKDAsIDAsIGNvbD0ncmVkJykKCm51bS5iaW5zIDwtIDEwCmhpc3QoZml0JHJlc2lkdWFscywgYnJlYWtzPW51bS5iaW5zLCBtYWluPXRpdGxlLnJlc2lkdWFsczEsIHhsYWI9J1RlbXBlcmF0dXJlJywgY29sPSdyZWQnKQoKcXFub3JtKGZpdCRyZXNpZHVhbHMsIG1haW49cGFzdGUoJ05vcm1hbCBRLVEgUGxvdCB3aXRoJywgdGl0bGUucmVzaWR1YWxzMSksIGNleC5tYWluPTEpCnFxbGluZShmaXQkcmVzaWR1YWxzLCBjb2w9J3JlZCcpCmBgYAoKYGBge3J9CiMgQXR0ZW1wdCBmb3IgTXVsdGlwbGUgUmVncmVzc2lvbnMKZGF0YSRNaWRuaWdodHMgPC0gMApkYXRhJE1pZG5pZ2h0c1t3aGljaChkYXRhJEhvdXI8NildIDwtIDEKZGF0YSRNb3JuaW5ncyA8LSAwCmRhdGEkTW9ybmluZ3Nbd2hpY2goZGF0YSRIb3VyPj02ICYgZGF0YSRIb3VyPDExKV0gPC0gMSAKZGF0YSROb29uIDwtIDAKZGF0YSROb29uW3doaWNoKGRhdGEkSG91cj49MTEgJiBkYXRhJEhvdXI8MTUpXSA8LSAxCmRhdGEkQWZ0ZXJub29uIDwtIDAKZGF0YSRBZnRlcm5vb25bd2hpY2goZGF0YSRIb3VyPj0xNSAmIGRhdGEkSG91cjwyMCldIDwtIDEKZGF0YSROaWdodHMgPC0gMApkYXRhJE5pZ2h0c1t3aGljaChkYXRhJEhvdXI+PTIwKV0gPC0gMQpgYGA=
>>>>>>> 79bd799c1946ef878aa178d035150404c135a16c
>>>>>>> 8826eee1488bdd27557439752deda8eb4e450389
>>>>>>> d4f5f9c0a005e74c03c52f2335922402dbf39c0f